JAVA SDK并发报,最核心的便是对管程的实现。
并发领域的两大问题,互斥和同步:
互斥:同一时刻只允许一个线程访问共享资源,使用Lock解决。
同步:线程之间如何通信,协作?使用Condition解决。
这两个关键字与synchronized的区别?
synchronized没办法解决《破坏不可抢占条件》,原因是synchronized申请资源如果申请不到,则线程直接进入阻塞状态了,啥也干不了,对于已经锁定的资源,也不会释放。
而这不是我们希望的,我们希望有这样一把互斥锁:
1、能够响应中断
2、支持超时
3、非阻塞地获取锁
而以上正好对应了Lock接口的三个方法:
1、void lockInterruptibly()
2、boolean tryLock(long time, TimeUnit unit)
3、boolean tryLock();
--------
如何保证可见性?
synchronized关键字是如何保证可见性的呢,实际是通过synchronized的Happen-before规则;
同理,JAVA SDK中的Lock是如何保证可见性的呢?实际也是通过volatile的Happen-before规则,
实际在Lock内部,有一个被声明为volatile的state关键字,在执行加锁和释放锁的同时,会分别进行state的读写,
来保证加锁和解锁,以及下一次加锁代码内,所有变量的值,被刷新到各个工作内存,从而保证类共享成员变量的可见性。
-------
可重入锁
线程可以重复的获得同一把锁
------
使用可重入锁的时候,你可以定义公平锁和非公平锁,灵活配置公平(等待时间长短)策略。
-----
用锁的最佳实践:
1、永远只在更新对象的成员变量时加锁
2、永远只在访问可变的成员变量时加锁
3、永远不要在调用其他对象的方法时加锁
========
Task类的定义
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Task {
private final Lock lock = new ReentrantLock();
private final Condition addCondition = lock.newCondition();
private final Condition subCondition = lock.newCondition();
private static int num = 0;
private volatile List<String> list = new LinkedList<>();
public void add() {
lock.lock();
try {
while (list.size() == 4) {
System.out.println("await list size : " + list.size());
System.out.println("await Current thread : " + Thread.currentThread().getName());
System.out.println("============");
this.addCondition.await();
}
num++;
list.add("add banana :" + num);
System.out.println("list size : " + list.size());
System.out.println("Current thread : " + Thread.currentThread().getName());
System.out.println("============");
this.subCondition.signal();
} catch (InterruptedException e) {
System.out.println("=======InterruptedException e=====");
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void sub() {
lock.lock();
try {
while (list.size() == 0) {
this.subCondition.await();
}
num--;
System.out.println("subtract banana :" + list.get(0));
list.remove(0);
System.out.println("list size : " + list.size());
System.out.println("Current thread : " + Thread.currentThread().getName());
System.out.println("============");
this.addCondition.signal();
} catch (InterruptedException e) {
System.out.println("=======InterruptedException e=====");
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
添加数据和移除数据的线程类:
public class AddThread implements Runnable {
private Task task;
public AddThread(Task task) {
this.task = task;
}
@Override
public void run() {
this.task.add();
}
}
public class SubThread implements Runnable {
private Task task;
public SubThread(Task task) {
this.task = task;
}
@Override
public void run() {
this.task.sub();
}
}
测试类:
public class TestReentreLock {
public static void main(String [] args) {
Task task = new Task();
Thread t1 = new Thread(new AddThread(task));
t1.setName("add Thread 1");
t1.start();
Thread t2 = new Thread(new AddThread(task));
t2.setName("add Thread 2");
t2.start();
Thread t3 = new Thread(new AddThread(task));
t3.setName("add Thread 3");
t3.start();
Thread t4 = new Thread(new AddThread(task));
t4.setName("add Thread 4");
t4.start();
Thread t5 = new Thread(new AddThread(task));
t5.setName("add Thread 5");
t5.start();
Thread t6 = new Thread(new AddThread(task));
t6.setName("add Thread 6");
t6.start();
Thread ts1 = new Thread(new SubThread(task));
ts1.setName("sub Thread 1");
ts1.start();
Thread ts2 = new Thread(new SubThread(task));
ts2.setName("sub Thread 2");
ts2.start();
}
}
执行结果:
com.wang.lock.TestReentreLock
list size : 1
Current thread : add Thread 1
============
list size : 2
Current thread : add Thread 3
============
list size : 3
Current thread : add Thread 4
============
list size : 4
Current thread : add Thread 2
============
await list size : 4
await Current thread : add Thread 5
============
await list size : 4
await Current thread : add Thread 6
============
subtract banana :add banana :1
list size : 3
Current thread : sub Thread 1
============
list size : 4
Current thread : add Thread 5
============
subtract banana :add banana :2
list size : 3
Current thread : sub Thread 2
============
list size : 4
Current thread : add Thread 6
============