synchronized关键字实现的锁不容易控制,java提供了Lock接口来实现锁机制。
两者的主要区别在于:
- 1)synchronized是java内置关键字,而Lock是接口;
- 2)synchronized可以自动的释放锁,比如代码执行完成,出现异常等,也可以通过wait()方法手动释放锁;但是Lock需要用unlock方法手动释放锁。
- 3)synchronized锁可重入,不可判断,非公平,Lock锁可重入,可公平可不公平,可判断;
- 4)用synchronized的两个线程,如果线程A获得锁并阻塞,线程B会一直等待下去,而Lock锁不一定会持续等待
(1) Lock实现锁的同步
使用Lock实现同步示例:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDem
{
static Lock lock = new ReentrantLock();
public static void main(String[] args)
{
new Thread(new Runnable(){
@Override
public void run()
{
lockMethod(lock);
}
},"thread1").start();
new Thread(new Runnable(){
@Override
public void run()
{
lockMethod(lock);
}
},"thread2").start();
}
public static void lockMethod(Lock lock){
lock.lock();
System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
for(int i = 0; i < 5; i++){
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("thread : " + Thread.currentThread().getName() + " " + i);
}
lock.unlock();
}
}
(2)lock实现锁的等待/通知
使用lock condition中的await方法和signal方法实现线程之间的等待/通知,同一个condition之间可以实现互相等待通知,不同的condition可以实现隔离。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockDemo2
{
private Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
public static void main(String[] args)
{
LockDemo2 demo2 = new LockDemo2();
new Thread(new Runnable(){
@Override
public void run()
{
demo2.await(demo2.condition1);
}
},"thread1").start();
new Thread(new Runnable(){
@Override
public void run()
{
demo2.await(demo2.condition2);
}
},"thread2").start();
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
new Thread(new Runnable(){
@Override
public void run()
{
demo2.signal(demo2.condition1);
}
},"thread3").start();
}
public void await(Condition condition){
try
{
lock.lock();
System.out.println(Thread.currentThread().getName() + "开始await");
condition.await();
System.out.println(Thread.currentThread().getName() + "结束await");
}
catch (InterruptedException e)
{
e.printStackTrace();
}finally
{
lock.unlock();
}
}
public void signal(Condition condition){
try
{
lock.lock();
System.out.println(Thread.currentThread().getName() + "开始signal");
condition.signal();
System.out.println(Thread.currentThread().getName() + "结束signal");
}catch (Exception e){
e.printStackTrace();
}finally
{
lock.unlock();
}
}
}
运行结果:thread2 await之后,由于没有现成被通知到,所以不能结束await.
thread1开始await
thread2开始await
thread3开始signal
thread3结束signal
thread1结束await
(3)lock实现读写锁
读写锁 ReentrantReadWriteLock实现读写锁ReadWriteLock,加锁lock.readLock.lock()/lock.writeLock.lock,
解锁lock.readLock.unlock()/ lock.writeLock.lock()。
读写锁能够实现,读读共享,读写/写读互斥,写写互斥。
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LockDemo3
{
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public static void main(String[] args)
{
LockDemo3 demo3 = new LockDemo3();
new Thread(new Runnable()
{
@Override
public void run()
{
demo3.readLock();
}
},"thread1").start();
new Thread(new Runnable()
{
@Override
public void run()
{
demo3.readLock();
}
},"thread2").start();
new Thread(new Runnable()
{
@Override
public void run()
{
demo3.writeLock();
}
},"thread3").start();
new Thread(new Runnable()
{
@Override
public void run()
{
demo3.writeLock();
}
},"thread4").start();
}
//读锁
public void readLock(){
try
{
lock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "获取到读锁" + System.currentTimeMillis());
Thread.sleep(3000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}finally
{
lock.readLock().unlock();
}
}
//写锁
public void writeLock(){
try
{
lock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "获取到写锁" + System.currentTimeMillis());
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}finally
{
lock.writeLock().unlock();
}
}
}
运行结果:
thread1获取到读锁1551929162893
thread2获取到读锁1551929162904
thread3获取到写锁1551929166201
thread4获取到写锁1551929169498
Process finished with exit code 0
参考博文: https://blog.csdn.net/xlgen157387/article/details/78197583