ReentrantLock

有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级。

this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决方案,后面jdk干脆就提供了一个Lock类。

伪代码:

Lock lock = new ReentrantLock();//新建一个lock

Condition condition = lock.newCondition();//获取条件

method1(){

  try{

    lock.lock();

    代码块;

    lock.unlock();

    后续代码块;

  }

}

method2(){

  try{

    lock.lock();

    代码块;

    lock.signal();

  }

}

单condition操作:

 import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class UseCondition { private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition(); public void method1(){
try {
lock.lock();
System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
Thread.sleep(3000);
System.out.println("当前线程:" + Thread.currentThread().getName() + "释放锁..");
condition.await(); // Object wait
System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行...");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void method2(){
try {
lock.lock();
System.out.println("当前线程:" + Thread.currentThread().getName() + "进入..");
Thread.sleep(3000);
System.out.println("当前线程:" + Thread.currentThread().getName() + "发出唤醒..");
condition.signal(); //Object notify
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public static void main(String[] args) { final UseCondition uc = new UseCondition();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
uc.method1();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
uc.method2();
}
}, "t2");
t1.start(); t2.start();
} }

执行结果:

解释:线程1调用method1方法,线程2调用同一对象的method2方法,线程1先启动,线程1获取锁,进入method1的代码块,线程2也启动了,单是线程2被锁定,直到线程1发出lock.unlock()了,线程1才将锁释放,这时线程2获取锁,执行method2的代码块,线程2发出lock.signal(); 线程1才继续执行后续代码块。

多condition操作:

 import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; public class UseManyCondition { private ReentrantLock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition(); public void m1(){
try {
lock.lock();
System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待..");
c1.await();
System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void m2(){
try {
lock.lock();
System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待..");
c1.await();
System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void m3(){
try {
lock.lock();
System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待..");
c2.await();
System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void m4(){
try {
lock.lock();
System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
c1.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void m5(){
try {
lock.lock();
System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒..");
c2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public static void main(String[] args) { final UseManyCondition umc = new UseManyCondition();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
umc.m1();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
umc.m2();
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
umc.m3();
}
},"t3");
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
umc.m4();
}
},"t4");
Thread t5 = new Thread(new Runnable() {
@Override
public void run() {
umc.m5();
}
},"t5"); t1.start(); // c1
t2.start(); // c1
t3.start(); // c2 try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} t4.start(); // c1
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t5.start(); // c2 } }

执行结果:

解释:t1、t2线程都是用第一个condition c1,t3线程用第二个condition c2,t4线程发出c1.signalAll() 唤醒t1和t2线程,t5发出c2.signal()唤醒t3线程。

ReentrantReadWriteLock

读写分离锁,读读共享、写写互斥、读写互斥。

 import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; public class UseReentrantReadWriteLock { private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private ReadLock readLock = rwLock.readLock();
private WriteLock writeLock = rwLock.writeLock(); public void read(){
try {
readLock.lock();
System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
Thread.sleep(3000);
System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
} catch (Exception e) {
e.printStackTrace();
} finally {
readLock.unlock();
}
} public void write(){
try {
writeLock.lock();
System.out.println("当前线程:" + Thread.currentThread().getName() + "进入...");
Thread.sleep(3000);
System.out.println("当前线程:" + Thread.currentThread().getName() + "退出...");
} catch (Exception e) {
e.printStackTrace();
} finally {
writeLock.unlock();
}
} public static void main(String[] args) { final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
urrw.read();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
urrw.read();
}
}, "t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
urrw.write();
}
}, "t3");
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
urrw.write();
}
}, "t4"); t1.start();
t2.start(); // t1.start(); // R
// t3.start(); // W // t3.start();
// t4.start();
}
}

解释:t1和t2都是读,是共享的,可同时获得readLock同时进入read方法执行。t1是读和t3是写,是互斥的,只有t1执行完t3才能执行。t3、t4都是写,是互斥的,只有等t3执行完t4才能继续。

最新文章

  1. CF732D. Exams[二分答案 贪心]
  2. web框架--bottle
  3. html中 table的结构 彻底搞清 caption th thead等
  4. Hololens开发笔记之Gesture手势识别(单击,双击)
  5. C# ManualResetEvent的使用
  6. Swift动画编程指南-02 Swift动画是怎么炼成的
  7. 【转】C#综合揭秘——通过修改注册表建立Windows自定义协议
  8. android开发 wifi开发不稳定性测试
  9. CLOUDSTACK接管VCENTER,意外频出,但最终搞定
  10. 有关UIWebView的SSL总结
  11. 在PL/SQL/sqlplus客户端 中如何让程序暂停几秒钟
  12. 团队作业8----第二次项目冲刺(beta阶段)5.25
  13. spring之集合注入
  14. 插入排序算法java
  15. Arcgis瓦片--js客户端加载
  16. 7Linux存储结构和磁盘划分
  17. 掌握PHP垃圾回收机制
  18. 【数学建模】day08-数理统计III
  19. java使用jdbc连接oracle(其他数据库类似)
  20. FindResource () RT_HTML 为什么总是出错呢 ?

热门文章

  1. html标签学习
  2. 5分钟让你掌握css3阴影、倒影、渐变小技巧!
  3. eCharts 数据转换json
  4. iOS 汉字的拼音
  5. MYSQL离线安装
  6. 网页万能排版布局插件,web视图定位布局创意技术演示页
  7. DependencyResolver.Current
  8. exynos4412中断编程
  9. JAVA操作LDAP的详解(JLDAP)
  10. JAVA开发中遇到的小白点