Java并发编程学习笔记(1)

1. wait - notify 使用方法

synchronized(lock) {
	while(条件不成立) {
	lock.wait();
}
 // 执行任务
}
//其他线程
synchronized(lock) {
	lock.notifyAll();
}

2. join 和 GuardedObject 保护性暂停模式的区别

  • 保护性暂停模式:一个线程等另一个线程的结果
  • join :一个线程等另一个线程的结束

3. 常见线程安全类

  • String
  • Integer
  • StringBuffer
  • Random
  • Vector
  • Hashtable
  • java.util.concurrent 包下的类
    这里说它们是线程安全的是指,多个线程调用它们同一个实例的某个方法时,是线程安全的。

4. sleep(long n) 和 wait(long n) 的区别

  1. sleep 是 Thread 方法,而 wait 是 Object 的方法
  2. sleep 不需要强制和 synchronized 配合使用,但 wait 需要
    和 synchronized 一起用
  3. sleep 在睡眠的同时,不会释放对象锁的,但 wait 在等待的时候会释放对象锁
  4. wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify()或者 notifyAll() 方法。sleep()方法执行完成后,线程会自动苏醒。

5. 线程之间的转态转换

(1) NEW ===> RUNNABLE

  • 线程调用 Thread.start() 方法

(2) RUNNABLE <===> WAITING

  • t 线程用 synchronized(obj) 获取了对象锁后,
    调用 obj.wait() 方法时,t 线程从 RUNNABLE --> WAITING。
    调用 obj.notify() , obj.notifyAll() , t.interrupt() 时, 若:
    a. 竞争锁成功,t 线程从 WAITING --> RUNNABLE
    b. 竞争锁失败,t 线程从 WAITING --> BLOCKED
  • 当前线程调用另一线程 t.join() 方法时,当前线程从 RUNNABLE --> WAITING
    t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从 WAITING --> RUNNABLE
  • 线程调用 LockSupport.park() 方法,从 RUNNABLE --> WAITING ;
    调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,会让目标线程从 WAITING --> RUNNABLE

(3) RUNNABLE <===>TIMED_WAITING

  • 调用 obj.wait(long n) 方法时,t 线程从 RUNNABLE --> TIMED_WAITING ;
    t 线程等待时间超过了 n 毫秒,或调用 obj.notify() , obj.notifyAll() , t.interrupt() 时:
    竞争锁成功,t 线程从 TIMED_WAITING --> RUNNABLE
    竞争锁失败,t 线程从 TIMED_WAITING --> BLOCKED
  • 当前线程调用 t.join(long n) 方法时,当前线程从 RUNNABLE --> TIMED_WAITING(注意是当前线程在t 线程对象的监视器上等待);
    当前线程等待时间超过了 n 毫秒,或 t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从
    TIMED_WAITING --> RUNNABLE
  • 当前线程调用 Thread.sleep(long n) ,当前线程从 RUNNABLE --> TIMED_WAITING ;
    当前线程等待时间超过了 n 毫秒,当前线程从 TIMED_WAITING --> RUNNABLE
  • 当前线程调用 LockSupport.parkNanos(long nanos)LockSupport.parkUntil(long millis) 时,当前线
    程从 RUNNABLE --> TIMED_WAITING ;
    调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,或是等待超时,会让目标线程从
    TIMED_WAITING–> RUNNABLE

(4) RUNNABLE <===> BLOCKED

  • t 线程用 synchronized(obj) 获取了对象锁时如果竞争失败,从 RUNNABLE --> BLOCKED ;
    持有 obj 锁线程的同步代码块执行完毕,会唤醒该对象上所有 BLOCKED 的线程重新竞争,如果其中 t 线程竞争
    成功,从 BLOCKED --> RUNNABLE ,其它失败的线程仍然 BLOCKED

(5) RUNNABLE <===> TERMINATED
当前线程所有代码运行完毕,进入 TERMINATED

6. 定位死锁

检测死锁可以用jps 定位进程 id,再用 jstack 定位死锁,使用 jconsole工具 :

jps 定位进程 id

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7. 活锁

活锁是指线程间资源冲突激烈,引起线程不断的尝试获取资源,不断的失败。活锁有点类似于线程饥饿,虽然资源并没有被别人持有,但由于各种原因而无法得到。最常见的原因是进程组的执行顺序不合理,导致某些先需要的资源被后置。活锁和死锁的不同在于,活锁的状态是变化的,只是无法达到目的。活锁有可能在一定时间后自动解开,但死锁不能。
解决:合理分配线程组的执行顺序,交错执行。

8. ReentrantLock(对象级别)

相对于 synchronized 它具备如下特点

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量
  • 与 synchronized 一样,都支持可重入

基本用法:lock和unlock成对出现

// 获取锁,也乐意放在try块中
reentrantLock.lock();
try {
 // 临界区
} finally {
 // 释放锁
 reentrantLock.unlock();
}

可重入

可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁
如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住

可打断

等待锁的过程中,可以用interrupt打断等待

ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(() -> {
 	log.debug("启动...");
	 try {
		 lock.lockInterruptibly();
 	} catch (InterruptedException e) {
 		e.printStackTrace();
 		log.debug("等锁的过程中被打断");
 		return;
 	}
 	try {
 		log.debug("获得了锁");
 	} finally {
 		lock.unlock();
 	}
}, "t1");

lock.lock();
log.debug("获得了锁");
t1.start();
try {
 	sleep(1);
	 t1.interrupt();
	 log.debug("执行打断");
} finally {
 	lock.unlock();
}

锁超时

线程在获取锁的过程中,如果其他线程持有的锁一直没有释放,线程不会一直死等,线程会等待一段时间,判断是否获取锁成功。

lock.trylock() //返回布尔值
lock.tryLock(long timeout, TimeUnit unit)

公平锁

ReentrantLock默认不公平

条件变量

synchronized 中也有条件变量,当条件不满足时进入 waitSet 等待
ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持多个条件变量的,这就好比synchronized 是那些不满足条件的线程都在一间休息室等消息
而 ReentrantLock 支持多间休息室
使用要点:
await 前需要获得锁
await 执行后,会释放锁,进入 conditionObject 等待
await 的线程被唤醒(或打断、或超时)取重新竞争 lock 锁
竞争 lock 锁成功后,从 await 后继续执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值