我们今天来学习一下线程安全的问题:
线程安全是在多线程编程中,有可能会出现同时访问同一个 共享、可变资源 的情况,始终都不会导致数据破坏以及其他不该出现的结果。这种资源可以是一个变量、一个对象、一个文件等。
在我们学习高并发的时候,我们为了防止我们的数据被几个线程同时运行来进行数据的操作,这样会造成数据的破坏,最会系统显示给我们的是一个错误的数据。但是我们计算机系统运行的软件特别多,所以我们肯定想要多线程来运行程序,这样效率特别高,但是我们也遇到了问题,就是两个数据被同两个线程共同运行时,如何保持数据的正确,所以我们引入了锁这个概念。
synchronized锁
Java内置锁通过synchronized关键字使用,使用其修饰方法或者代码块,就能保证方法或者代码块以同步方式执行。有对象锁和类锁(static方法(类)和class(对象)上枷锁)区分,两者不冲突可以并行存在。
Lock锁
Lock是java的一个interface接口,这里我们使用实现类ReentrantLock。
显式锁(ReentrantLock)正式为了解决这些灵活需求而生,ReentrantLock的字面意思是可重入锁,可重入的意思是线程可以同时多次请求同一把锁,而不会自己导致自己死锁。
区别
1、synchronized修饰的代码在执行异常时,jdk会自动释放线程占有的锁,不需要程序员去控制释放锁,因此不会导致死锁现象发生(synchronized可以修饰方法,建议锁的范围越小越好)但是,当Lock发生异常时,如果程序没有通过unLock()去释放锁,则很可能造成死锁现象,因此Lock一般都是在finally块中释放锁;
try {
// 加锁
lock.lock();
} finally {
// 释放锁
lock.unlock();
}
2、Lock可以让等待锁的线程响应中断处理,如tryLock(long time, TimeUnit unit),而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够中断,程序员无法控制.
3、Lock的实现类ReentrantReadWriteLock提供了readLock()和writeLock()用来获取读锁和写锁的两个方法,这样多个线程可以进行同时读操作;