线程基础知识_Synchronized_ThreadAPI_自定义锁_获取线程运行时异常

本文详细介绍了Java中的Synchronized关键字,包括monitor enter和exit,以及线程的sleep、yield、wait、notify/notifyAll、interrupt、interrupted和join方法的使用。同时,讨论了如何根据Thread API实现自定义锁,并讲解了如何获取和处理线程运行时异常。
摘要由CSDN通过智能技术生成

Synchronized

synchronized包含monitor enter, monitor exit 2个JVM指令(遵循happens-before原则), 执行monitor exit之前必须存在monitor enter指令.
由于每个对象与一个monitor产生关联, 线程执行monitor enter时, 就会获取monitor的lock, monitor中存在计数器, 用于记录当前lock被获取的情况, 当线程已经获取了lock, 再次进行线程重入, lock往上自增.
与之相反, 当线程执行到monitor exit时, 对应的monitor计数器就会自减

  • this monitor: synchronized修饰的对象是this
public synchronized void test(){
   
	//...
}
//A实现Runnable接口
A a = new A();
new Thread(a).start();
new Thread(a).start();
  • class monitor: synchronized修饰的对象是class
public synchronized static void test() {
   
	//...
}
或者
public void test() {
   
	synchronized(A.class) {
   
		//...
	}
}
//A实现Runnable接口
A a1 = new A();
A a2 = new A();
//此时a1 与a2 共用一个class monitor
new Thread(a1).start();
new Thread(a2).start();

Thread API

sleep, yield, wait, notify/notifyAll, interrupt, interrupted, join

  • sleep
    Thread.sleep(), 线程休眠, 但休眠不会释放锁资源, 线程从running => block的状态切换, 可以使用thread.interrupt中断睡眠
  • yield
    Thread.yield(), 当前线程放弃CPU资源(CPU资源不紧张, 将忽略), 线程从running => runnable的状态切换, 因此不能使用interrupt中断处于runnable状态的线程
  • wait
    线程放弃锁资源, 并进入与锁关联的waitSet集合, 状态变化: Running => Blocked, 可以设定
    object.wait()等价于object.wait(0), 表示阻塞时间是永远
    注: wait必须在同步代码内. waitSet依赖于锁资源, 没有在同步代码内, 抛出IllegalMonitorStateException
    wait与sleep相似点:
1. 都能使线程阻塞
2. 都是可中断
3. wait属于Object, sleep属于Thread
4. wait需要在同步代码块中, sleep不需要
5. wait状态下, 将会是否锁资源, sleep不会释放锁资源
6. sleep执行一段自动退出阻塞状态, wait(long)一样.
  • notify/notifyAll
    notify随机唤醒waitSet集合中某一线程, notifyAll唤醒waitSet集合中所有的线程, 被唤醒的线程重新争抢锁资源, 争抢到之后, 接着刚才wait的地方往后执行
    注: notify必须在同步代码内. waitSet依赖于锁资源, 没有在同步代码内, 抛出IllegalMonitorStateException
  • interrupt
    打断当前线程阻塞状态, 可使用interrupt进行中断的方法如下:
object.wait(), object(long), Thread.sleep(long), thread.join(), Selector.wakeup()
public void interrupt() {
   
        if (this != Thread.currentThread())
            checkAccess();
        synchronized (blockerLock) {
   
            Interruptible b = blocker;
            if (b != null) {
   
             	//设置中断标识, interrupt0属于native方法
                interrupt0();          
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

当线程使用休眠方法进入阻塞状态后, 使用thread.interrupt设置中断标志, 随后线程被中断, 抛出InterruptedException, 线程终止运行
isInterrupt: 用于判断线程是否被中断, 从下面源码看出, 判断线程是否被中断, 不会清除中断标志

   public boolean isInterrupted() {
   
   		//native方法, clearInterrupted设置为false
        return isInterrupted(false);
    }

思考: wait, sleep, yield被中断后会不会清除中断标志

/**
 * 测试
 * @author regotto
 */
public class InterruptTest {
   

    private static final Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
   
        Thread thread = new Thread(() -> {
   

            synchronized (lock) {
   
                try {
   
                    System.out.println("1.isInterrupted: " + Thread.currentThread().isInterrupted());
                    lock.wait();
                } catch (InterruptedException e) {
   
                    System.out.println("2.isInterrupted: " + Thread.currentThread().isInterrupted());
                }
            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值