java线程同步问题

一般,有3种使用锁进行同步的方法
a.方法同步,例如public synchronized void xxx()...
b.静态方法同步,例如public static synchronized void xxx()...
c.程序块同步,例如
...
synchronized(object oLock) //注意:object不一定是该类的实例
{
...
}

在用法a中,当某线程执行方法xxx时,jvm会锁定该类的实例,直到方法xxx执行完毕。执行xxx的过程看看成是这样的:
*请求得到类实例的实例锁,假如有其他线程在执行,则等待;
*得到实例锁,执行xxx;
*执行完毕,释放实例锁;
注意,这个过程是jvm完成的,我们只需要把某个对象方法声明为synchronized即可,实例锁可以理解为实例本身。


在用法b中,当某线程执行静态方法xxx时,也是有jvm控制经过以上的3个步骤,所不同的是由于此时不存在类实例(静态方法嘛),所

以用法a中实例锁被实例的类的锁取代,其实对我们编程来讲,几乎没有任何区别,我们只需要把静态方法声明为synchronized即可。
在用法c中,oLock可以被理解为一个传接棒,它可以是任何类的实例,当某个线程试图访问声明为synchronized的程序块的时候,jvm

判断oLock是否被锁定,假如没有被锁定,则锁定oLock并执行该程序块。执行完毕释放该锁。
在对象级使用锁(实例锁)通常是一种比较粗糙的方法,设想一下,假如一个对象可能去访问N个共享资源,那么假如有一个线程独占

了该对象,而仅仅是为了使用其中的一项资源的话,也会造成想访问其它资源的线程也处于堵塞状态。用程序块同步可以很好解决这个问题,

以下是使用被称为Fine_Grain_Lock的例子,看,效果是不是很high:
[code]
class FineGrainLock {
MyMemberClass x, y;
Object xlock = new Object(), ylock = new Object();
public void foo() {
synchronized(xlock) {
//access x here
}
//do something here - but don't use shared resources
synchronized(ylock) {
//access y here
}
}

public void bar() {
synchronized(this) {
//access both x and y here
}
//do something here - but don't use shared resources
}
}
[/code]
2.notify/wait/notifyAll,上面是交给jvm使用同步方法处理共享资源问题,可以理解为抢占型的共享资源解决方案,而使用

notify/wait/notifyall可以在程序中控制对共享资源的访问,实现一种合作型的共享资源解决方案。一个小例子:
[code]
//WNNa:wait/notify/notifyAll
public class WNNa implements Runnable
{
private static Object oLock = new Object();
public void run()
{
try
{
synchronized(oLock)
{
TwoBoy t = (TwoBoy)Thread.currentThread();
if(t.getName() == "Mike")
{
oLock.wait();
t.eat();
oLock.notify();
oLock.wait();
t.drink();
}
else
{
t.eat();
oLock.notify();
oLock.wait();
t.drink();
oLock.notify();
}
}
}
catch(Exception ex)
{
System.out.println("Error in synchronized:" + ex.getMessage());
}
}
public WNNa()
{
TwoBoy t1 = new TwoBoy(this,"Tom");
TwoBoy t2 = new TwoBoy(this,"Mike");
t1.start();
t2.start();
}
public static void main(String argv[])
{
new WNNa();
}
}

class TwoBoy extends Thread
{
private String strName = "";
public TwoBoy(Runnable t,String name)
{
super(t,name);
strName = name;
}
public void drink()
{
System.out.println(strName + " drink!");
}
public void eat()
{
System.out.println(strName + " eat!");
}
}
[/code]
在上面的例子中,我们可以控制线程按照业务逻辑运行,而非简单的排它的使用共享资源的问题了。
3.信号量方案:在有N个共享资源而有M个线程的情况下(M>>N),需要用到信号量。信号量代表可用资源的数目,线程需要使用资源时首先判

断是否有足够的资源,没有的话等待,直到其它线程释放资源为止,得到资源后,信号量应减去该线程使用的资源数目,待这些资源使用完毕

,线程应释放这些资源。
[code]
class Semaphore {
private int count;
public Semaphore(int n) {
this.count = n;
}

public synchronized void acquire() {
while(count == 0) {
try {
wait();
} catch (InterruptedException e) {
//keep trying
}
}
count--;
}

public synchronized void release() {
count++;
notify(); //alert a thread that's blocking on this semaphore
}
}
[/code]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值