您的位置:首页 > 编程语言 > Java开发

java 7 并发 初级 学习记录(3)

2014-06-27 00:00 162 查看
1.Lock

另一种同步方式,显示地在代码中使用lock()方法,指明在此处进行加锁了,当然还有unlock()方法,指明在此处解锁。Lock的使用比synchronized同步块更加灵活,但也更容易出错,使用不当就会发生死锁,所以要非常小心。

Lock是一个接口,一般使用它的某些实现类如最常用的ReentrantLock,参考如下代码:

public class Target {

private Lock lock = new ReentrantLock();

public void testLock(){
System.out.println(Thread.currentThread().getName() + " 进入testLock方法");
lock.lock();
System.out.println(Thread.currentThread().getName() + " 获取锁");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 执行完毕,准备解锁");
lock.unlock();
}
}

----------------------------------------------------------------------------------------------
public class JavaCurrent {

public static void main(String[] args) {
Target target = new Target();
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new Task(target));
t.start();
}
}

}

class Task implements Runnable{

private Target target;

public Task(Target target) {
this.target = target;
}

@Override
public void run() {
target.testLock();
}

}

执行结果:
Thread-0 进入testLock方法
Thread-0 获取锁
Thread-3 进入testLock方法
Thread-1 进入testLock方法
Thread-2 进入testLock方法
Thread-4 进入testLock方法
Thread-0 执行完毕,准备解锁
Thread-3 获取锁
Thread-3 执行完毕,准备解锁
Thread-1 获取锁
Thread-1 执行完毕,准备解锁
Thread-2 获取锁
Thread-2 执行完毕,准备解锁
Thread-4 获取锁
Thread-4 执行完毕,准备解锁

lock还有一个tryLock()的方法,它的意思是,尝试着去获取锁,如果获取了,返回true,如果已经被别的线程占用了,则返回false。注意的是,它不会等待,也就是说不管有没有获取锁,它都会立刻返回结果,并且向下执行,不会被堵塞。如果线程获取了锁,那么在执行完毕之前必须调用unlock()解锁,不然线程会永远堵塞。

2.死锁

当两个线程在获得各自锁,还没有解锁的情况下,相互试图获取对方的锁,这样就会造成死锁!双方都在等待对方先解锁。

public class DeadLock {

private Lock lock1 = new ReentrantLock();

private Lock lock2 = new ReentrantLock();

public void testDeadLock1(){
System.out.println(Thread.currentThread().getName() + "进入testDeadLock1方法");
lock1.lock();//先让线程使用lock1加锁
System.out.println(Thread.currentThread().getName() + "获取lock1锁");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock2.lock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock2.unlock();
System.out.println(Thread.currentThread().getName() + "lock1解锁");
lock1.unlock();
}

public vo
3ff0
id testDeadLock2(){
System.out.println(Thread.currentThread().getName() + "进入testDeadLock2方法");
lock2.lock();//先让线程使用lock1加锁
System.out.println(Thread.currentThread().getName() + "获取lock2锁");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock1.lock();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock1.unlock();
System.out.println(Thread.currentThread().getName() + "lock2解锁");
lock2.unlock();
}
}
---------------------------------------------------------------------------------------
public class JavaCurrent {

public static void main(String[] args) {
DeadLock target = new DeadLock();
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new Task1(target));
t.start();
}
}

}

class Task1 implements Runnable{

private DeadLock deadLock;

public Task1(DeadLock deadLock) {
this.deadLock = deadLock;
}

@Override
public void run() {
deadLock.testDeadLock1();
deadLock.testDeadLock2();
}

}

运行结果:
Thread-0进入testDeadLock1方法
Thread-2进入testDeadLock1方法
Thread-1进入testDeadLock1方法
Thread-4进入testDeadLock1方法
Thread-3进入testDeadLock1方法
Thread-0获取lock1锁
Thread-0lock1解锁
Thread-0进入testDeadLock2方法
Thread-0获取lock2锁
Thread-2获取lock1锁

可见在thread0获取lock2的锁,同时thread2获取lock1的锁之后,发生了死锁。

3.Condition

有没有想过Lock中如何使用wait,notify,notifyall?lock有一个newCondition()方法,返回一个Condition对象,这个对象的功能有点类似于同步块中的参数对象。可以使用condition中的await(),signal(),signalAll()来代替。下面来改写第二片中最后一个例子:其他类不用变,需要修改Target类

public class Target {

private Lock lock = new ReentrantLock();

private Condition condition = lock.newCondition();

private int allowIn = 3;//允许3个线程经过setwait()

private int count = 0;

public void setWait(){
System.out.println(Thread.currentThread().getName()+ " 进入setWait");
lock.lock();
System.out.println(Thread.currentThread().getName()+ " 进入setWait中的同步块中");
if(count > allowIn){
try {
System.out.println(Thread.currentThread().getName()+ " 发现已经超出最大数值了,只能等待了!");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);//休眠1秒
System.out.println(Thread.currentThread().getName()+ " 处理setWait完毕,退出方法,释放锁");
count ++ ;
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}

public void setNotify(){
System.out.println(Thread.currentThread().getName()+ " 进入setNotify");
lock.lock();
System.out.println(Thread.currentThread().getName()+ " 进入setNotify中的同步块中");
if(count > allowIn){
System.out.println(Thread.currentThread().getName()+ " 发现已经超出最大数值了,数值清理!");
count = 0;
condition.signalAll();
}else{
try {
TimeUnit.SECONDS.sleep(2);//休眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 处理setNotify完毕,退出方法,释放锁");
}
lock.unlock();
}
}

运行结果和原来的例子基本一致。

Lock还有其他一些实现类可以提供给我们使用,具体使用也是类似,可自行参考其他资料。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: