A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 山水游客 中级黑马   /  2012-6-27 11:23  /  1275 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 孙胜录 于 2012-6-27 14:35 编辑

当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 为什么?

4 个回复

倒序浏览
本帖最后由 周兴中 于 2012-6-27 11:45 编辑

当一个线程进入一个对象的一个synchronized方法后,其他线程也无法进入其对象的其他方法(根本进入不了任何方法),因为在同一个时间内,只有一个线程有CPU执行权,而同步synchronized之后的方法,是为了让CPU执行完被同步的方法之后,释放执行权,然后再和其他线程一起竞争CPU执行权,谁拿到执行权,谁才再有执行的权利.
如果不加同步修饰,那么当执行到某个方法的一部分语句之后,就有可能被其他CPU抢到执行权,那么容易出现错误(在操作共享数据时).

可以参考生产者和消费者代码:

  1. class ProducerConsumerDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Resource r = new Resource();

  6.                 Producer pro = new Producer(r);
  7.                 Consumer con = new Consumer(r);

  8.                 Thread t1 = new Thread(pro);
  9.                 Thread t2 = new Thread(pro);
  10.                 Thread t3 = new Thread(con);
  11.                 Thread t4 = new Thread(con);

  12.                 t1.start();
  13.                 t2.start();
  14.                 t3.start();
  15.                 t4.start();

  16.         }
  17. }

  18. /*
  19. 对于多个生产者和消费者。
  20. 为什么要定义while判断标记。
  21. 原因:让被唤醒的线程再一次判断标记。


  22. 为什么定义notifyAll,
  23. 因为需要唤醒对方线程。
  24. 因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

  25. */


  26. class Resource
  27. {
  28.         private String name;
  29.         private int count = 1;
  30.         private boolean flag = false;
  31.                         //  t1    t2
  32.         public synchronized void set(String name)
  33.         {
  34.                 while(flag)
  35.                         try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)
  36.                 this.name = name+"--"+count++;

  37.                 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
  38.                 flag = true;
  39.                 this.notifyAll();
  40.         }


  41.         //  t3   t4  
  42.         public synchronized void out()
  43.         {
  44.                 while(!flag)
  45.                         try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
  46.                 System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
  47.                 flag = false;
  48.                 this.notifyAll();
  49.         }
  50. }

  51. class Producer implements Runnable
  52. {
  53.         private Resource res;

  54.         Producer(Resource res)
  55.         {
  56.                 this.res = res;
  57.         }
  58.         public void run()
  59.         {
  60.                 while(true)
  61.                 {
  62.                         res.set("+商品+");
  63.                 }
  64.         }
  65. }

  66. class Consumer implements Runnable
  67. {
  68.         private Resource res;

  69.         Consumer(Resource res)
  70.         {
  71.                 this.res = res;
  72.         }
  73.         public void run()
  74.         {
  75.                 while(true)
  76.                 {
  77.                         res.out();
  78.                 }
  79.         }
  80. }
复制代码
回复 使用道具 举报
一个线程进入一个对象的一个synchronized方法后,其他线程也进入不了其对象的其他方法,因为在同一个时间内,只有一个线程有CPU执行权,而同步synchronized之后的方法,是为了让CPU执行完被同步的方法之后,释放执行权,然后再和其他线程一起竞争CPU执行权,谁拿到执行权,谁才再有执行的权利. synchronized的可以加在方法上,也可以用synchronized代码块。。。

回复 使用道具 举报
  1. /*对象的synchronized方法不能进入了,其他线程还是可以进入此对象的非同步方法的
  2. */
  3. public class ThreadTest {
  4. int i = 0;
  5. int j = 0;

  6. public static void main(String[] args) {
  7.         final ThreadTest threadTest = new ThreadTest();
  8.         new Thread() {
  9.                 public void run() {
  10.                 threadTest.printI();
  11.                 }
  12.         }.start();



  13.         new Thread() {
  14.                 public void run() {
  15.                 threadTest.printJ();
  16.                 }
  17.         }.start();
  18. }

  19.         public synchronized void printI() {
  20.                 while (i < 100)
  21.                 System.out.println("i==" + i++);
  22.         }

  23.         public void printJ() {
  24.                 while (j < 50)
  25.                 System.out.println("j==" + j++);
  26.         }
  27. }
复制代码
回复 使用道具 举报
不可以 ,但是在synchronized方法引用了一个全局的变量,synchronized方法

还没有运行完成的期间,在另外的一个方法中就可以修改synchronized方法的这

个变量

例如:A和B 一起去吃饭,在进一个大门,A站在门口不进去,B就不能进去,
     但是现在有个专门的老师通道,C老师和B玩得好,C就可以把B带从老师通道进去
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马