stan451219097 2013-08-30 22:36
浏览 229
已采纳

关于ThreadLocal解决哲学家就餐问题的疑问

众所周知,在java中有两种方法(或者以上)解决并发的临界资源问题

一种是通过加锁来实现的,即synchronized。

还有一种是ThreadLocal的方法来解决的

但是本人还是对后者有不理解的地方(或者说是什么情况下该用synchronized,什么情况下该用),特此来请教各路大神

同步采用了"以时间换空间的思想",而ThreadLocal采用"以空间换取时间的"思想

public class Chopsticks
{
String name;
private static ThreadLocal enable=new ThreadLocal(){
public Boolean initialValue(){
return true;
}
};
//boolean Enable = true;

public Chopsticks(String name) 
{ 
this.name = name; 
} 

//synchronized
public boolean pickup(){
if(this.enable.get()==false){
return false;
}
this.enable.set(false);
return true;
// try {
// while(Enable==false) //筷子被用
// {
// this.wait();

// }
// this.Enable =false; //筷子没有被用
// }
// catch (Exception e)
// {
// e.getMessage();
// }
}
public void putdown() {
// this.Enable =true;
// this.notifyAll();
this.enable.set(true);
}
}

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class zhexuejia extends Thread
{
String name; //属性

Chopsticks left; 

Chopsticks right; 

public zhexuejia(String name, Chopsticks l, Chopsticks r) {  //初始化 
this.name = name; 
left = l; 
right = r; 
} 

@Override 
public void run() { 
left.pickup(); 
System.out.println(name + " 眼明手快,一把抓起 "+left.name); 
right.pickup(); 
System.out.println(name + " 眼明手快,一把抓起 "+right.name); 
System.out.println(name + " 开始进餐"); 
try { 
Thread.sleep(500); 
} catch (InterruptedException e) { 
// TODO 自动生成 catch 块 
e.printStackTrace(); 
} 
System.out.println(name + " 酒足饭饱,打了个饱嗝,心满意足的放下了 "+left.name+" 和 " +right.name); 
left.putdown(); 
right.putdown(); 

} 
public static void main(String []args) 
{ 
    Chopsticks k1 = new Chopsticks("1号"); 
    Chopsticks k2 = new Chopsticks("2号"); 
    Chopsticks k3 = new Chopsticks("3号"); 
    Chopsticks k4 = new Chopsticks("4号"); 
    Chopsticks k5 = new Chopsticks("5号"); 


    zhexuejia z1=new zhexuejia("1",k5,k1); 
    zhexuejia z2=new zhexuejia("2",k1,k2); 
    zhexuejia z3=new zhexuejia("3",k2,k3); 
    zhexuejia z4=new zhexuejia("4",k3,k4); 
    zhexuejia z5=new zhexuejia("5",k4,k5); 
    ExecutorService e= Executors.newFixedThreadPool(10); //将诸线程加入线程池,并发执行 
    e.execute(z5); 
    e.execute(z2); 
    e.execute(z3); 
    e.execute(z4); 
    e.execute(z1); 
} 

}

执行下来的结果与哲学家就餐的问题不符,问题还是在ThreadLocal的问题上

问题的根源就在于什么情况用锁机制,什么情况用ThreadLocal的机制
Spring中的源代码大量使用了ThreadLocal来保持同步,不知道这种同步和哲学家就餐有什么不同呢?

疑问

  • 写回答

1条回答 默认 最新

  • zyn010101 2013-08-31 11:10
    关注

    我们来看下ThreadLocal的使用场景:
    ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
    每个线程访问的都是该线程对该对象的副本或者copy(各个线程运行自己的,彼此之间并不进行数据共享或通过该对象进行线程通信),并不修改原始对象,在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。

    你所给的代码中,你的本意是用enable来担任synchronized的锁的角色,希望用enable来控制各个线程的调用,也就是说它是一个共享对象,完全不适应ThreadLocal的场景,你应该用synchronized的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作