java中实现同步的两种方式syschronized和lock的区别和联系_第1页
java中实现同步的两种方式syschronized和lock的区别和联系_第2页
java中实现同步的两种方式syschronized和lock的区别和联系_第3页
java中实现同步的两种方式syschronized和lock的区别和联系_第4页
java中实现同步的两种方式syschronized和lock的区别和联系_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

java中实现同步的两种方式:syschronized和lock的区别和联系Lock是java.util.concurrent.locks包下的接口,Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题,我们拿Java线程(二)中的一个例子简单的实现一下和sychronized一样的效果,代码如下:?12345678910111213141516171819202122232425262728publicclassLockTest{publicstaticvoidmain(String[]args){finalOutputter1output=newOutputter1();newThread(){publicvoidrun(){output.output("zhangsan");};}.start();newThread(){publicvoidrun(){output.output("lisi");};}.start();}}classOutputter1{privateLocklock=newReentrantLock();//锁对象publicvoidoutput(Stringname){//TODO线程输出方法lock.lock();//得到锁try{for(inti=0;iSystem.out.print(name.charAt(i));}}finally{lock.unlock();//释放锁}}}这样就实现了和sychronized一样的同步效果,需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁自动释放,而用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内。如果说这就是Lock,那么它不能成为同步问题更完美的处理方式,下面要介绍的是读写锁(ReadWriteLock),我们会有一种需求,在对数据进行读写的时候,为了保证数据的一致性和完整性,需要读和写是互斥的,写和写是互斥的,但是读和读是不需要互斥的,这样读和读不互斥性能更高些,来看一下不考虑互斥情况的代码原型:?123456789101112131415161718192021222324252627282930313233343536373839404142434445publicclassReadWriteLockTest{publicstaticvoidmain(String[]args){finalDatadata=newData();for(inti=0;i<3;i++){newThread(newRunnable(){publicvoidrun(){for(intj=0;j<5;j++){data.set(newRandom().nextInt(30));}}}).start();}for(inti=0;i<3;i++){newThread(newRunnable(){publicvoidrun(){for(intj=0;j<5;j++){data.get();}}}).start();}}}classData{privateintdata;//共享数据publicvoidset(intdata){System.out.println(Thread.currentThread().getName()+"准备写入数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}this.data=data;System.out.println(Thread.currentThread().getName()+"写入"+this.data);}publicvoidget(){System.out.println(Thread.currentThread().getName()+"准备读取数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"读取"+this.data);}}部分输出结果:?12345678910Thread-1准备写入数据Thread-3准备读取数据Thread-2准备写入数据Thread-0准备写入数据Thread-4准备读取数据Thread-5准备读取数据Thread-2写入12Thread-4读取12Thread-5读取5Thread-1写入12我们要实现写入和写入互斥,读取和写入互斥,读取和读取互斥,在set和get方法加入sychronized修饰符:?12publicsynchronizedvoidset(intdata){...}publicsynchronizedvoidget(){...}部分输出结果:?12345678910Thread-0准备写入数据Thread-0写入9Thread-5准备读取数据Thread-5读取9Thread-5准备读取数据Thread-5读取9Thread-5准备读取数据Thread-5读取9Thread-5准备读取数据Thread-5读取9我们发现,虽然写入和写入互斥了,读取和写入也互斥了,但是读取和读取之间也互斥了,不能并发执行,效率较低,用读写锁实现代码如下:?123456789101112131415161718192021222324252627282930313233classData{privateintdata;//共享数据privateReadWriteLockrwl=newReentrantReadWriteLock();publicvoidset(intdata){rwl.writeLock().lock();//取到写锁try{System.out.println(Thread.currentThread().getName()+"准备写入数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}this.data=data;System.out.println(Thread.currentThread().getName()+"写入"+this.data);}finally{rwl.writeLock().unlock();//释放写锁}}publicvoidget(){rwl.readLock().lock();//取到读锁try{System.out.println(Thread.currentThread().getName()+"准备读取数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"读取"+this.data);}finally{rwl.readLock().unlock();//释放读锁}}}部分输出结果:?12345678910111213Thread-4准备读取数据Thread-3准备读取数据Thread-5准备读取数据Thread-5读取18Thread-4读取18Thread-3读取18Thread-2准备写入数据Thread-2写入6Thread-2准备写入数据Thread-2写入10Thread-1准备写入数据Thread-1写入22Thread-5准备读取数据从结果可以看出实现了我们的需求,这只是锁的基本用法,锁的机制还需要继续深入学习。

在java中有两种方式实现原子性操作(即同步操作):

1)使用同步关键字synchronized

2)使用lock锁机制其中也包括相应的读写锁

?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160packagecom.xiaohao.test;

importjava.util.Random;import;importjava.util.concurrent.locks.ReadWriteLock;importjava.util.concurrent.locks.ReentrantLock;importjava.util.concurrent.locks.ReentrantReadWriteLock;

publicclassTest{publicstaticvoidmain(String[]args){finalLockTestlock=newLockTest();//输出张三newThread(){publicvoidrun(){lock.test("张三张三张三张三张三张三张三张三张三张三");}}.start();

//输出李四newThread(){publicvoidrun(){lock.test("李四李四李四李四李四李四李四李四李四李四");System.out.println("\n---------------------------------------------------------------");}}.start();

//---------------------------------------------------------------//模拟写入数据的for(inti=0;i<3;i++){newThread(){publicvoidrun(){for(intj=0;j<5;j++){//lock.set(newRandom().nextInt(30));lock.set2(newRandom().nextInt(30));

}}}.start();

}//模拟读取数据的for(inti=0;i<3;i++){newThread(){publicvoidrun(){for(intj=0;j<5;j++){//lock.get();lock.get2();}}}.start();}

}}

classLockTest{privateLocklock=newReentrantLock();//创建普通的锁privateReadWriteLockreadWriteLock=newReentrantReadWriteLock();//创建读写锁privateintdata;//共享数据

//实现同步的方法一使用同步关键字synchronizedpublicsynchronizedvoidtest(Stringname){//下面的相关操作是一个原子性的操作//lock.lock();//得到锁try{for(inti=0;i<name.length();i++){System.out.print(name.charAt(i));}}finally{//lock.unlock();//释放锁}}

//实现同步的方法二使用lock锁机制publicvoidtest2(Stringname){//下面的相关操作是一个原子性的操作lock.lock();//得到锁try{for(inti=0;i<name.length();i++){System.out.print(name.charAt(i));}}finally{lock.unlock();//释放锁}}

//使用set方法模拟写入数据//使用synchronized实现了读读,写写,读写之间的互斥,但读读之间的互斥是没有什么必要的publicsynchronizedvoidset(intdata){System.out.println(Thread.currentThread().getName()+"准备写入数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}this.data=data;System.out.println(Thread.currentThread().getName()+"写入"+this.data);}

//使用get方法模拟读取数据//使用synchronized实现了读读,写写,读写之间的互斥,但读读之间的互斥是没有什么必要的publicsynchronizedvoidget(){System.out.println(Thread.currentThread().getName()+"准备读取数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"读取"+this.data);}

//使用set方法模拟写入数据//使用读写锁实现了写写,读写之间的互斥,但读读之间的互斥是没有什么必要的publicvoidset2(intdata){readWriteLock.writeLock().lock();//获取写入锁try{System.out.println(Thread.currentThread().getName()+"准备写入数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}this.data=data;System.out.println(Thread.currentThread().getName()+"写入"+this.data);}finally{readWriteLock.writeLock().unlock();}}

//使用get方法模拟读取数据//使用读写锁实现了写写,读写之间的互斥,但读读之间的互斥是没有什么必要的publicvoidget2(){//获取相应的读锁readWriteLock.readLock().lock();try{System.out.println(Thread.currentThread().getName()+"准备读取数据");try{Thread.sleep(20);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"读取"+this.data);}finally{//释放相应的写锁readWriteLock.readLock().unlock();}}

}

线程同步经典版:?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899packagecom.xiaohao.test;

importjava.util.concurrent.locks.ReentrantReadWriteLock;

publicclassTest2{

publicstaticvoidmain(String[]args){

finalLockTest2lockTest=newLockTest2();

for(inti=0;i<3;i++){

newThread(){

publicvoidrun(){

try{

for(intj=0;j<3;j++){

lockTest.setValue();

}}catch(InterruptedExceptione){

//TODOAuto-generatedcatchblocke.printStackTrace();

}

}

}.start();

}

for(inti=0;i<3;i++){

newThread(){

publicvoidrun(){

try{

for(intj=0;j<3;j++){

lockTest.getValue();

}

}catch(InterruptedExceptione)

{//TODOAuto-generatedcatchblocke.printStackTrace();}

}

}.start();

}

}

}

classLockTest2{

intdata=0;

ReentrantReadWriteLocklock=newRe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论