并发编程最容易遇到的问题就是就是安全问题,因此解决方式有两种

  • 使用同步方法或同步代码块(Synchronized关键字)

  • 使用锁机制(ReentranLock)

同步方法和同步代码块(Synchronized关键字)是基于JVM实现的,相对比较粗粒度优点就是简单粗暴不容易出错,但是性能也不是很好。

锁机制是一种显示锁,能够实现更细粒度的控制。风险就是需要自己控制锁的释放,否则容易引发死锁。

ReentrantLock

ReentrantLock:可重入锁,ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。下面通过一些实例看具体看一下如何使用ReentrantLock。大家可以去看一下Lock接口,自己以前尝试自定义一个读写锁出来,就是实现Lock接口,然后结合AQS(AbstractQueuedSynchronizer,调度器)来实现。

看代码

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadSafe {
private static Lock lock = new ReentrantLock();
private volatile static Integer i = 10;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println("thread1获得锁");
System.out.println("T1 i的值:" + i);
i++;
System.out.println("T1 i的值:" + i);
}finally {
System.out.println("thread1释放锁");
lock.unlock();
}
}
});
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
try {
System.out.println("thread获得锁");
i = 12;
System.out.println("i的值:" + i);
}finally {
System.out.println("thread释放锁");
lock.unlock();
}
}
});
thread.start();
thread1.start();
// for (int x = 0; x < 15; x++) {
// System.out.println(thread.getState() + "XXXX");
// System.out.println(thread1.getState() + "X");
// }
}
}

这样也解决线程安全的问题。

在Lock接口中有如下方法:

public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}

其中lock()方法用来获取锁。如果锁已被其他线程获取,则进行等待。
unlock()释放锁,如果对象没有上锁,则抛出异常。

tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。

tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。

lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。也就使说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程

Condition我们可以把它当做多线程见协调通信的一个工具类, newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。

最新文章

  1. 深入学习jQuery元素尺寸和位置操作
  2. Guava中Predicate的常见用法
  3. Python Webk框架学习 Flask
  4. unity, terrain道出为obj
  5. C语言 malloc calloc realloc alloc 在分配内存时的 区别
  6. ThinkPHP项目CMS内容管理系统开发视频教程【20课】(3.02GB)
  7. linux runlevel
  8. delphi 注册表操作(读取、添加、删除、修改)完全手册
  9. ubuntu下新建VPN连接
  10. phpwamp单身狗模式的详解与分析,单身狗模式/即霸体模式的作用讲解。
  11. luogu P5303 [GXOI/GZOI2019]逼死强迫症
  12. C# -- 抽象类与抽象方法
  13. Postgres通用翻页函数
  14. 常见的CSS代码无效问题
  15. 20145320《网络对抗》注入Shellcode并执行
  16. POJ3268(KB4-D spfa)
  17. 零基础学习hadoop到上手工作线路指导(编程篇)
  18. 2018.09.28 牛客网contest/197/B面积并(二分+简单计算几何)
  19. js-验证码插件gVerify.js
  20. ArcGIS按字段属性分割文件

热门文章

  1. php大文件断点续传
  2. Linux的磁盘分区
  3. MapServer教程
  4. python-zx笔记9-单元测试
  5. vue 如何通过监听路由变化给父级路由菜单添加active样式
  6. shell脚本一一项目3
  7. TensorFlow学习笔记3-从MNIST开始
  8. Jmeter录制web和app脚本
  9. Linux服务正常启动,Linux服务器能访问,但是外部机器不能访问
  10. java_第一年_JavaWeb(4)