0
点赞
收藏
分享

微信扫一扫

TeeChart for.NET Crack

一条咸鱼的干货 2023-07-15 阅读 29

ReentrantLock和synchronized都是用来确保线程的安全性,为了在线程并发时保证线程安全,我们必须给需要进行的操作方法加“锁”。

synchronized的实现方式:

使用Synchronized关键字可以将一段代码逻辑,用一把锁给锁起来,只有获得了这把锁的线程才访问。并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住的代码,从而确保代码的线程安全。

synchronized 关键字的用法:

synchronized修饰实例方法(当前对象当“锁”):

    // 递增
public void add() {
for (int i = 0; i < 10000; i++) {
synchronized (this) {
Counter1.count += 1;
}
}
}

// 递减
public synchronized void dec() {
for (int i = 0; i < 10000; i++) {
Counter1.count -= 1;
}
}

 synchronized修饰静态方法(当前对象的class对象当“锁”):

    // 递增
public void add() {
for (int i = 0; i < 10000; i++) {
synchronized (Counter2.class) {
Counter2.count += 1;
}
}
}

// 递减
public synchronized static void dec() {
for (int i = 0; i < 10000; i++) {
Counter2.count -= 1;
}
}

  synchronized修饰代码块(Object对象当“锁”):

//递增线程
class AddThread extends Thread{
private static final Object lock=new Object();

@Override
public void run() {
for(int i=0;i<10000;i++) {
synchronized (lock) {
Counter.count+=1;
}
}
}
}

注意:

当一个线程访问一个对象的synchroized(this)代码块时,另一个线程仍可以访问该对象的非synchroized(this)代码块;

离开synchroized(this)代码块后,该线程所持有“锁”会自动释放。

ReentrantLock的使用:

从Java 5开始,引入了一个高级处理并发java.util.concurrent包,它提供了大量更高级的并发功能,能大大简化多线程程序的编写。

使用ReentrantLock代码参考如下:

class Counter {
// 用于计数的公共变量
public static int count = 0;
//创建锁
private final ReentrantLock lock = new ReentrantLock();

// 递增
public void add() {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
Counter.count += 1;
} finally {
lock.unlock();
}
}
}

// 递减
public void dec() {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
Counter.count -= 1;
} finally {
lock.unlock();
}
}
}
}

 ReentrantLock与synchronized的区别:

 ReentrantLocksynchronized
锁实现机制AQS监视器Monitor
获取锁可以通过tryLock()尝试获取锁,更灵活线程抢占模型
释放锁必须显示通过unlock()释放锁自动释放
锁类型支持公平锁和非公平锁非公平锁
可重入性可重入可重Rett 

ReentrantLock 区别于 synchronized来说,它不仅可以开锁关锁,它还可以尝试锁tryLock(),因此在实际的引用场景中,当产生“死锁”时,ReentrantLock可以进行一些额外处理而不是无限等待下去。所以说ReentrantLock的安全性更好一些。

举报

相关推荐

0 条评论