JUC包实现的同步机制,原理以及简单用法总结

      除了用Synchronized关键字修饰同步块,让线程获取某对象的锁实现多线程操作共享变量的同步外,还可以使用java.util.concurrent包。并且,juc包机制下的同步更灵活。juc包的所有锁都实现自Lock接口和ReadWriteLock接口,下面分别总结。

(图片来源于网络)

Lock接口

     Lock在java.util.concurrent.locks包中,Lock是一个接口,我们一般使用的是它的实现类:ReentrantLock (可重入锁)。ReentrantLock类的主要方法有:

     

void lock() //获取调用此代码的对象的锁,失败就等待

boolean tryLock() //尝试获取调用此代码的对象的锁,失败返回false,不等待

boolean tryLock(long t) //尝试获取调用此代码的对象的锁,失败等待 t 时间后返回false

void lockInterruptibly() // 获取调用此代码的对象的锁,失败就等待。但是这个等待可以中断 (与syn不同,syn只有wait、join、 sleep的线程可悲中断)

void unlock() //释放锁(必须手动写明)

使用示例如下:

public class Main {
    public static void main(String[] args) {
        Test t = new Test();
        t.readAndWriteSomething(); //main线程要对 t 进行一些需要同步的操作  
}
}
class Test {
    ...
    int value = 1;
    Lock l = new ReentrantLock();

    public void readAndWriteSomething() {
        l.lock();     //获取 t 的锁
        .....;   //从 t 读出写入一些内容
        l.unlock();  //释放 t 的锁
    }
}

大概使用方法就是上面这样,至于其他的tryLock、lockInterruptibly等方法就看具体情况灵活应用了。但是手动释放锁的操作十分重要,不然其他线程可能会饥饿,甚至出现死锁现象。

ReadWriteLock接口

        我们知道,多个线程读取并不会造成一些危险。所以我们想,可不可以有一种锁,在读操作的时候可以多个线程共享(即锁可以同时由几个线程共同持有),写操作时又变为互斥锁。ReadWriteLock接口的实现类ReentrantReadWriteLock可以实现这种操作。

ReentrantReadWriteLock中的两个方法:

Lock readLock()     //返回一个读锁,时可以共享的 
Lock writeLock()    //返回一个写锁,不可以共享

使用示例:

    

public class Main {
    public static void main(String[] args) {
        Test t = new Test();
        t.readAndWriteSomething(); //main线程要对 t 进行一些需要同步的操作 
}
} class Test { ... int value = 1; Lock l = new ReentrantReadWriteLock(); public void readAndWriteSomething() { l.readLock().lock(); //获取 t 的读锁 .....; //从 t 读出一些内容 l.readLock().unlock(); //释放 t 的读锁

l.writeLock().lock() //获取 t 的写锁 ...... //从 t 写入一些内容 l.writeLock().unlock(); //释放 t 的写锁 } }

可以看到,并没有多复杂,无非把一个对象的锁拆成读锁、写锁两部分而已,其中读锁是共享锁,写锁互是斥锁。读操作时获取读锁,写操作时获取写锁。提高效率

 总结二者区别

Synchronized是关键字,lock机制是一组类实现;

Synchronized没有共享锁,lock机制有读锁(共享的);

Synchronized没有lock灵活,lock可以随时获取对象的锁,但需要手动释放(这也是灵活的表现);

lock机制下有tryLock返回获取锁的结果,成功or失败;

lock机制下获取锁失败的线程可以被中断。

当然,lock机制下,每个有同步块的对象需要持有实现了Lock接口的类的实例,通过这个实例去修改对象的锁状态。

原文地址:https://www.cnblogs.com/shen-qian/p/11218178.html