请大家讨论一下线程同步的问题及实现的思路
最近接触这个问题,感觉挺陌生的。
想学习点东西,希望大家能提出自己的意见和想法,先谢谢大家了!
最近接触这个问题,感觉挺陌生的。
想学习点东西,希望大家能提出自己的意见和想法,先谢谢大家了!
解决方案 »
- 关于下载的问题
- SSH2结构下openSessionInView无效,求指教!查了一天了,谢谢大家了...
- 在TOMCAT中部署J2EE项目时出的问题
- 一个异常,大家来帮忙分析一下,困扰我一天了,估计是大家都碰到过的
- 最近开发EJB3消息驱动BEAN时遇到了一个这样的问题 Exception in thread "main" javax.naming.CommunicationException 网上似乎没有看到这样的问题 就在某个地方看到一哈 但给出的解决方法??
- jsp中操作数据库的问题
- Hibernate3.0 有没有好的IDE生成ORM和POJO
- 谁有好的学习EJB的范例或书籍?推荐一下,不胜感激.
- 请问如何启动J2EE服务器?(J2EE SDK 1.3.1)
- 项目部署域名,紧急求助
- 谁做过医疗系统的项目,能给个设计书看看吗?
- java替换字符问题
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:
Java代码
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
}
} 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
}
}
2.notify/wait/notifyAll,上面是交给jvm使用同步方法处理共享资源问题,可以理解为抢占型的共享资源解决方案,而使用 notify/wait/notifyall可以在程序中控制对共享资源的访问,实现一种合作型的共享资源解决方案。一个小例子:
Java代码
//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!");
}
} //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!");
}
}
在上面的例子中,我们可以控制线程按照业务逻辑运行,而非简单的排它的使用共享资源的问题了。
3.信号量方案:在有N个共享资源而有M个线程的情况下(M>>N),需要用到信号量。信号量代表可用资源的数目,线程需要使用资源时首先判 断是否有足够的资源,没有的话等待,直到其它线程释放资源为止,得到资源后,信号量应减去该线程使用的资源数目,待这些资源使用完毕 ,线程应释放这些资源。
Java代码
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
}
}