java lock使用_Java:多线程,线程同步,同步锁(Lock)的使用(ReentrantLock、ReentrantReadWriteLock)...

关于线程的同步,可以使用synchronized关键字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock对象。本文探讨Lock对象。

synchronized与java.util.concurrent.locks.Lock 的相同点:Lock能完成synchronized所实现的所有功能;主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放, 并且必须在finally从句中释放。

一:先来一段简单的代码

packagecom.clzhang.sample.thread;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;public class LockThread1 implementsRunnable {private Integer key = 0;//锁对象

private Lock lock = newReentrantLock();

@Overridepublic voidrun() {//需要结果是key实现自增长,如果没有同步块,则可能会出现重复key值的现象

lock.lock();try{

key++;

System.out.println(Thread.currentThread().getName()+ ":" +key);try{

Thread.sleep(10);

}catch(InterruptedException e) {

}

}finally{//上述代码实现功能与使用sychronized同步代码块一样。//sychronized同步代码块或同步方法在代码执行完之后锁自动释放;而用Lock则需要手工释放锁。//为了保证锁最终被释放,释放锁代码放在finally块内。

lock.unlock();

}

}public static voidmain(String[] args) {

LockThread1 lt= newLockThread1();for(int i=0; i<100; i++) {new Thread(lt, "Thread" +i).start();

}

}

}

部分输出:

Thread86:95

Thread88:96

Thread90:97

Thread98:98

Thread92:99

Thread96:100

二:再来一段稍复杂的代码

packagecom.clzhang.sample.thread;import java.util.*;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;public class LockThread2 implementsRunnable {//内部类

classStudent {private int age = 0;public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}

}//全局变量定义

private int count = 0;private Student student = newStudent();//锁对象

private Lock lock1 = new ReentrantLock(false);private Lock lock2 = new ReentrantLock(false);

@Overridepublic voidrun() {

String currentThreadName=Thread.currentThread().getName();

System.out.println(currentThreadName+ " is running!");

lock1.lock();//使用重入锁

System.out.println(currentThreadName + " got lock1@Step1!");try{

count++;

Thread.sleep(3000);

}catch(Exception e) {

e.printStackTrace();

}finally{

System.out.println(currentThreadName+ " first:count=" + count + "\tage=" + this.student.getAge());

lock1.unlock();

}

lock2.lock();//使用另外一个不同的重入锁

System.out.println(currentThreadName + " got lock2@Step2!");try{

Random random= newRandom();int age = random.nextInt(100);this.student.setAge(age);

Thread.sleep(3000);

}catch(Exception ex) {

ex.printStackTrace();

}finally{

System.out.println(currentThreadName+ " second:count=" + count + "\tage=" + this.student.getAge());

lock2.unlock();

}

}public static voidmain(String[] args) {

LockThread2 lt= newLockThread2();for (int i = 1; i <= 3; i++) {

Thread t= new Thread(lt, "Thread" +i);

t.start();

}

}

}

输出:

Thread1 is running!

Thread1 got lock1@Step1!         // 线程1获取锁1

Thread3 is running!

Thread2 is running!

Thread1 first:count=1 age=0

Thread3 got lock1@Step1!

Thread1 got lock2@Step2!         // 线程3、1分别获取锁1、2

Thread3 first:count=2 age=13

Thread1 second:count=2 age=13     // count值已经被线程3更改;age是自己设置的。

Thread3 got lock2@Step2!

Thread2 got lock1@Step1!        // 线程3、2分别获取锁2、1

Thread2 first:count=3 age=34

Thread3 second:count=3 age=34     // count值已经被线程2更改;age是自己设置的。

Thread2 got lock2@Step2!        // 线程2获取锁2

Thread2 second:count=3 age=40     // 没人改count值了;age是自己设置的。

三:再来一段读写的代码

要求:写入和写入互斥,读取和写入互斥,读取和读取之间不互斥。

packagecom.clzhang.sample.thread;import java.util.*;importjava.util.concurrent.locks.ReadWriteLock;importjava.util.concurrent.locks.ReentrantReadWriteLock;public class LockThread3 implementsRunnable {//数据存放

private StringBuilder sb = newStringBuilder();//锁对象

private ReadWriteLock rwl = newReentrantReadWriteLock();

@Overridepublic voidrun() {if (Thread.currentThread().getName().startsWith("Read")) {

rwl.readLock().lock();//取到读锁

try{

System.out.println(Thread.currentThread().getName()+ "正在读取...");try{

Thread.sleep(500);

}catch(InterruptedException e) {

e.printStackTrace();

}

System.out.println(Thread.currentThread().getName()+ "结果:" +sb.toString());

}finally{

rwl.readLock().unlock();//释放读锁

}

}else if (Thread.currentThread().getName().startsWith("Write")) {

rwl.writeLock().lock();//取到写锁

try{

System.out.println(Thread.currentThread().getName()+ "正在写入...");try{

Thread.sleep(1000);

}catch(InterruptedException e) {

e.printStackTrace();

}

String writeData= "" + new Random().nextInt(100);

sb.append(writeData+ ",");

System.out.println(Thread.currentThread().getName()+ "结果:" +writeData);

}finally{

rwl.writeLock().unlock();//释放写锁

}

}else{//啥也不做行不

}

}public static voidmain(String[] args) {

LockThread3 lt= newLockThread3();for (int i=0; i<5; i++) {

Thread t= new Thread(lt, "Write" +i);

t.start();

}for (int i=0; i<5; i++) {

Thread t= new Thread(lt, "Read" +i);

t.start();

}

}

}

输出:

Write1正在写入...

Write1结果:25

Write0正在写入...

Write0结果:5

Read0正在读取...

Read2正在读取...

Read4正在读取...

Read2结果:25,5,

Read0结果:25,5,

Read4结果:25,5,

Write2正在写入...

Write2结果:77

Write4正在写入...

Write4结果:38

Read1正在读取...

Read3正在读取...

Read1结果:25,5,77,38,

Read3结果:25,5,77,38,

Write3正在写入...

Write3结果:77

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值