读书人

经验2-线程回顾之加深版-同步锁详解

发布时间: 2012-09-14 11:53:44 作者: rapoo

心得2--线程回顾之加深版--同步锁详解

这节与大家分析一下线程的高深部分,多线程的锁问题及同步问题,关键字:synchronized。下面从基础概念介绍起,后面与大家分享下两种单例模式:饿汉式和懒汉式中运行线程同步的情况。

1.互斥锁

μ 每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任意时刻,只能有一个线程访问该对象。

μ Java对象默认是可以被多个线程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。

μ 关键字synchronized用来与对象的互斥锁联系

μ 当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,即使该线程出现堵塞,该对象的被锁定状态也不会解除,其他线程任不能访问该对象。

2.synchronized关键字的使用方式有两种:

ˉ 用在对象前面限制一段代码的执行(同步代码块
public void push(char c){

sychronized(this){
data[index]=c;
index++
}
}

ˉ 用在方法声明中,表示整个方法为同步方法

public synchronized char pop(){

index--;

return data[index];

}

同步的两种表现形式简释为:

1).同步代码块

synchronized(对象){

需要同步的代码

}

2).同步函数: 使用的锁是this

public synchronized void show(){

}

同步代码块可以使用任意对象作为锁,同步方法使用的锁只有一个--this。static同步方法使用的锁是该方法所属类的对象。类型.class

μ 同步好处:解决了线程安全问题

μ 同步弊端

ü 降低了运行效率(判断锁是较为消耗资源的)

ü 同步嵌套,容易出现死锁

3. 死锁

两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:两个线程互相等待,都无法运行。

4.线程同步通信

为避免死锁,就应该让线程在进入阻塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会,Object类中定义了几个有用的方法:wait()、notify()、notifyAll()。

μ wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的线程就有机会访问该对象。

μ notify():唤醒调用wait()方法后被阻塞的线程。每次运行该方法只能唤醒一个线程。

μ notifyAll():唤醒所有调用wait()方法被阻塞的线程。

5. 单例中的同步:

懒汉式:

代码块方式:

classSingle{

private static Single s=null;

private Single(){}

public static Single getInstance(){

if(s==null)

synchronized(Singel.class){

if(s==null)

s=new Single();

}

return s;

}

函数方式:

classSingle{

private static Single s=null;

private Single(){}

public static synchronized SinglegetInstance(){

if(s==null)

s=newSingle()

return s;

}

Single.getInstance();

饿汉式:

classSingle{

private static Single s=new Single();

private Single(){}

public static Single getInstance(){

return s;

}

}

读书人网 >编程

热点推荐