黑马程序员技术交流社区

标题: 多线程关于synchronized问题 [打印本页]

作者: 创出一片辉煌    时间: 2012-7-24 18:07
标题: 多线程关于synchronized问题
线程操作案例——生产者和消费者
老师提出如何同步多线程,他采用了以下代码。(就是创造个set synchronized method还有一个 get synchronized method)
class Info{ // 定义信息类
private String name = "李四";  // 定义name属性
private String content = "父亲"  ;  // 定义content属性
public synchronized void set(String name,String content){
  this.setName(name) ; // 设置名称
  try{
   Thread.sleep(300) ;
  }catch(InterruptedException e){
   e.printStackTrace() ;
  }
  this.setContent(content) ; // 设置内容
}
public synchronized void get(){
  try{
   Thread.sleep(300) ;
  }catch(InterruptedException e){
   e.printStackTrace() ;
  }
  System.out.println(this.getName() +
   " --> " + this.getContent()) ;
}
public void setName(String name){
  this.name = name ;
}
public void setContent(String content){
  this.content = content ;
}
public String getName(){
  return this.name ;
}
public String getContent(){
  return this.content ;
}
};
class Producer implements Runnable{ // 通过Runnable实现多线程
private Info info = null ;  // 保存Info引用
public Producer(Info info){
  this.info = info ;
}
public void run(){
  boolean flag = false ; // 定义标记位
  for(int i=0;i<50;i++){
   if(flag){
    this.info.set("李四","父亲") ; // 设置名称
    flag = false ;
   }else{
    this.info.set("liming","son") ; // 设置名称
    flag = true ;
   }
  }
}
};
class Consumer implements Runnable{
private Info info = null ;
public Consumer(Info info){
  this.info = info ;
}
public void run(){
  for(int i=0;i<50;i++){
   this.info.get() ;
  }
}
};
public class ThreadCaseDemo02{
public static void main(String args[]){
  Info info = new Info(); // 实例化Info对象
  Producer pro = new Producer(info) ; // 生产者
  Consumer con = new Consumer(info) ; // 消费者
  new Thread(pro).start() ;
  new Thread(con).start() ;
}
};
我现在想知道的是如果我不创造一个set 和 get synchronized method,而是用
synchronized(this) 来表示,这样子代码应该也可以同步吧?以下是改的,但是运行的时候
结果却没有同步。这是为什么啊?
class Info { // 定义信息类
private String name = "李四"; // 定义name属性
private String content = "父亲"; // 定义content属性
public void setName(String name) {
  this.name = name;
}
public void setContent(String content) {
  this.content = content;
}
public String getName() {
  return this.name;
}
public String getContent() {
  return this.content;
}
};
class Producer implements Runnable { // 通过Runnable实现多线程
private Info info = null; // 保存Info引用
public Producer(Info info) {
  this.info = info;
}
public void run() {
  boolean flag = false; // 定义标记位
  for (int i = 0; i < 50; i++) {
   if (flag) {
    synchronized (this) {
     this.info.setName("李四") ;
     try {
      Thread.sleep(300);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     this.info.setContent("父亲");
    } // 设置内容
    flag = false;
   } else {
    synchronized (this) {
     this.info.setName("liming"); // 设置名称
     try {
      Thread.sleep(300);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     this.info.setContent("son");
    } // 设置内容
    flag = true;
   }
  }
}
};
class Consumer implements Runnable {
private Info info = null;
public Consumer(Info info) {
  this.info = info;
}
public void run() {
  for (int i = 0; i < 50; i++) {
   synchronized (this) {
    try {
     Thread.sleep(300);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    System.out.println(this.info.getName() + " --> "
      + this.info.getContent());
   }
  }
}
};
public class ThreadCaseDemo02 {
public static void main(String args[]) {
  Info info = new Info(); // 实例化Info对象
  Producer pro = new Producer(info); // 生产者
  Consumer con = new Consumer(info); // 消费者
  new Thread(pro).start();
  new Thread(con).start();
}
};

作者: 侯宪博    时间: 2012-7-25 02:18
本帖最后由 侯宪博 于 2012-7-25 12:50 编辑

额,这个。。
作者: 侯宪博    时间: 2012-7-25 12:50
楼主,辛苦。把自己的想法实现成代码是一个好习惯。。。
但是问问题要抓住重点,你这把代码全粘上来谁看了都会不淡定的。。。
你完全可以把代码简化一下,突出问题就可以了。
首先关于同步你老师用的是同步函数
同步函数持有对象的this引用,而set 和 get 在同一个类中
所以他们持有同一个this引用,所以可以同步
但是你用的是同步代码块
虽说你的对象都是this,但是你的两个同步代码块不在同一个类中
所以你的两个this不是同一个对象一个是Producer的对象一个是Consumer的this
想解决其实很简单,你的info对象可是同一个对象哦
你把info对象扔里面就哦啦。。。
希望对你有所帮助。。。
作者: 王志明    时间: 2012-7-25 13:16
楼主你还是没搞清楚线程同步的原理,多个线程想同步,就要抢一个对象锁才行,而你的两个线程各拿各的锁,怎么能同步呢应该这样写

Producer中:
synchronized (info) {

Consumer中:
synchronized (info) {


让这两个线程抢一个对象的锁去。。。

作者: 罗宵    时间: 2012-7-25 21:56
class Consumer implements Runnable 类中你用的 synchronized (this) 的锁是this,代表Consumer,
class Producer implements Runnable {类中你用的synchronized (this) 的锁是this,代表Producer ,
这两个方法中的锁不是同一把,所以相互间是锁不住的。
这两个类都是对Info进行操作。所以可以把Info当作参数传给Consumer(里面创建带参构造,传Info)和Producer(里面创建带参构造传Info) 。
在同步的时候,都以Info为锁。这样的话在主方法中
public class ThreadCaseDemo02 {
public static void main(String args[]) {
   Info info = new Info(); // 实例化Info对象
   Producer pro = new Producer(info); // 生产者
   Consumer con = new Consumer(info); // 消费者
   new Thread(pro).start();
   new Thread(con).start();
}就可以了
};




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2