sleep yield,守护线程,释放锁,死锁例子volatile

来源:互联网 发布:保险公司业务自助优化 编辑:程序博客网 时间:2024/06/16 15:49

1、Sleep与yield异同:

相同点:

(1)两者都是Thread类的静态方法,暂停处于运行态的线程。

(2)在线程执行同步代码块或同步方法中(synchronized),调用Thread.sleep或者Thread.yield,都不会释放同步监视器(锁)(suspend挂起后也不释放同步锁)

区别:

(1)优先级:sleep暂停线程后,会给其他线程执行机会,不考虑线程的优先级问题yield暂停后只有优先级高于或等于当前线程的线程才有执行机会。

(2)状态:sleep当前线程由运行态进入阻塞态;yield使当前线程由运行态到就绪态。

(3)异常:sleep方法在声明时抛出InterruptedException异常,所以在使用时要么try捕获要么throws抛出;而yield没有声明异常。

(4)移植性:sleep的移植性更好

2、线程优先级规则

高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完。还有线程1先被main调用,不代表它先执行完,当线程优先级差距大时,谁先执行完几乎与调用顺序无关。线程优先级还有一定的随机性,高优先级的线程不一定每次都先执行完。

3、守护线程(保姆线程)

注意先setDeament(true),在调用start才是守护线程,只要有前端线程守护线程就存在,当所有的前端线程执行完毕,守护线程也就执行完毕,典型的就是GC

4、是否释放锁

(1)breakreturn释放锁,并且会继续执行后面的程序

(2)Error 或者exception释放锁,但不继续执行后面程序

(3)Wait方法调用后释放锁,不执行后面程序

(4)Sleepyield、suspend,线程暂停但不释放锁。易引起死锁

5、死锁的例子

(1)Public void run(){While(true){i++;System.out.println(i); }} Public static void main(String[] args){ ...thread.suspend();//suspend没释放锁,println是synchronized方法,所以main线程调用print时出现阻塞。System.out.println(“main end”);...}


(2)

当类的对象flag=1时(T1),先锁定O1,睡眠500毫秒,然后锁定O2
T1在睡眠的时候另一个flag=0的对象(T2)线程启动,先锁定O2,睡眠500毫秒,等待T1释放O1
* T1睡眠结束后需要锁定O2才能继续执行,而此时O2已被T2锁定;
* T2睡眠结束后需要锁定O1才能继续执行,而此时O1已被T1锁定;
* T1T2相互等待,都需要对方锁定的资源才能继续执行,从而死锁。


class DeadLock implements Runnable {public int flag = 1;static Object o1 = new Object(), o2 = new Object();public void run() {System.out.println("flag=" + flag);if(flag == 1) {synchronized(o1) {//先锁定o1try {Thread.sleep(500);//休眠} catch (Exception e) {e.printStackTrace();}synchronized(o2) {//锁定o2System.out.println("1");}}}if(flag == 0) {synchronized(o2) {//锁定o2 try {Thread.sleep(500);} catch (Exception e) {e.printStackTrace();}//休眠synchronized(o1) {//锁定o1System.out.println("0");}}}}}public static void main(String[] args) {DeadLock t1 = new DeadLock();DeadLock t2 = new DeadLock();t1.flag = 1;t2.flag = 0;new Thread(t1).start();new Thread(t2).start();}}

6、

Volatile 并不能替代synchronized,因为volatile不具有原子性,不如对i++的多线程处理,有可能出现脏读的情况,而Java5后的原子类对于自增等情况是原子的。

假设:

Int i;

Volatile int j;

Int j;

Public int getI(){return i;}

Public int getj(){return j;}

synchronized public int getk(){return k;}

变量i,主内存中的变量i,拷贝到各个线程的线程栈中;每个线程每次调用的是自己线程栈内的拷贝变量i,只在一定情况下(当前线程执行完写入主线程)所以可能出现脏读情况。

Volatile变量j,每个线程都是从主内存中读取的变量,而不是线程栈,所以变量j对于任何线程具有可见性。

Synchronized在主内存区域同步到线程栈的内存。一般操作操作分为:(1)线程获得监视器this对象的对象锁;(2)线程栈内的数据被清除,从主内存中读入;(3)代码块被执行;(4)变量的任何改变安全地写入到主内存中;(5)释放对象锁。