Synchronized关键字详解

Synchronized关键字详解

Monitor对象

普通对象

wait()和notify()

只有获取了锁的线程才能够调用 wait() 方法和 notify() 方法。

可重入锁 ReentrantLock

通过 lockInterruptibly() 方法和 isHeldByCurrentThread() 方法来处理死锁

import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockTest {
    @Test
    public void lockInterruptedTest() throws InterruptedException {
        ReentrantLock lockA = new ReentrantLock();
        ReentrantLock lockB = new ReentrantLock();

        // 线程先对A加锁, 再对B加锁
        Thread threadX = new Thread(() -> {
            try {
                lockA.lockInterruptibly();
                TimeUnit.SECONDS.sleep(5);
                lockB.lockInterruptibly();

                // 真正执行的工作
                System.out.println(Thread.currentThread().getName() + " : finished!");

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (lockA.isHeldByCurrentThread()) {
                    lockA.unlock();
                }
                if (lockB.isHeldByCurrentThread()) {
                    lockB.unlock();
                }
            }
        }, "thread-X");

        Thread threadY = new Thread(() -> {
            try {
                lockB.lockInterruptibly();
                TimeUnit.SECONDS.sleep(5);
                lockA.lockInterruptibly();

                System.out.println(Thread.currentThread().getName() + " : finished!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (lockA.isHeldByCurrentThread()) {
                    lockA.unlock();
                }
                if (lockB.isHeldByCurrentThread()) {
                    lockB.unlock();
                }
            }

        }, "thread-Y");


        threadX.start();
        threadY.start();

        // 指定一个任务的超时时间, 如果在该时间内任务没有完成, 则认为发生死锁
        int timeout = 10 * 1000;
        threadY.join(timeout);
        //TODO: 这里应该使用if判断
        // 释放所拥有的锁
        threadY.interrupt();
        System.out.println(threadY.getName() + " : interrupt");

        TimeUnit.SECONDS.sleep(3);
        // TODO: 为什么这里不可以重新对线程使用start()?

        // 解决死锁
        System.out.println(Thread.currentThread().getName() + " : finished!");
    }
}

   转载规则


《Synchronized关键字详解》 熊水斌 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
锁
锁的两种实现可重入锁可以多次加锁, 加锁几次就要解锁几次 读写锁读写分离, 提高多线程的并发读的能力. 不同线程: 读锁和写锁互斥, 写锁和写锁互斥. 同一线程: 支持锁降级, 不支持锁升级(写锁级别比读锁高, 获取到写锁后可以继续获取
2023-03-14
下一篇 
Interrupt方法详解 Interrupt方法详解
Interrupt方法详解Interrupt打断阻塞态线程 打断阻塞态的线程会抛出异常,同时清空打断状态。该异常常用来作为唤醒手段 public class InterruptBlockedMain { public stat
2023-03-13
  目录