黑马程序员技术交流社区

标题: 同步代码块的问题 [打印本页]

作者: wzg1015    时间: 2014-10-26 22:23
标题: 同步代码块的问题
本帖最后由 wzg1015 于 2014-10-30 21:38 编辑

晕,好不容易打了一遍,出现错误了,重打
首先是多线程中的零时变量是否可以作为监视器,不可以的化为什么下面可行?
  1. public class Test {
  2.         protected final static ExecutorService pool = Executors.newFixedThreadPool(300);
  3.        private String name="";
  4.        //用于标记
  5.       int i=0;
  6.       /**需要测试的方法**/
  7.       public void setName(String name) {
  8.                synchronized (name) {  每次进入,name应该是一个新的临时变量,为什么开始可以正常
  9.                         i++;
  10.                         this.name=name+i;
  11.                         System.out.println(this.name);
  12.                 }
  13.            }
  14.         public static void main(String[] args) {
  15.                  Test test=new Test();
  16.                 for(int i=0;i<100;i++) {
  17.                          pool.execute(new Runnable() {
  18.                                 public void run() {
  19.                                  test.setName("测试");
  20.                                 }
  21.                         });
  22.                 }
  23.         }
  24. }
复制代码


     当不使用同步出现重复
        使用synchronized (name)  ,不出现重复,而且是标准顺序的,也就是0-99顺序排列
        使用synchronized (this.name) ,不出现重复,但是杂序,为什么区别这么大

作者: 嘿~~    时间: 2014-10-27 21:59
使用synchronized (name),这里的name是private  String name = " ";不是形参那个name。这个锁是固定的,持有锁才能进入,下一个程序要等到上一个程序释放锁才能进入,因此打印结果是有序的,
使用synchronized (this.name) ,这里的name是形参name。这个name不是固定的,是传入的,因此这个锁也就没作用了,打印结果就乱了,并且会出现重复的情况
作者: wzg1015    时间: 2014-10-27 22:12
嘿~~ 发表于 2014-10-27 21:59
使用synchronized (name),这里的name是private  String name = " ";不是形参那个name。这个锁是固定的, ...

请问为什么是反过来的?name没约束不是应该就是形参么,在方法里面使用this约束了,不是使用的对象的么,怎么变成形参了?
作者: 嘿~~    时间: 2014-10-27 22:18
在普通方法的synchronized()括号里的锁要么是this,要么是一个任意的固定对象,你觉得你传入的变化的形参可以吗,
作者: wzg1015    时间: 2014-10-27 22:23
嘿~~ 发表于 2014-10-27 22:18
在普通方法的synchronized()括号里的锁要么是this,要么是一个任意的固定对象,你觉得你传入的变化的形参可 ...
  1. public class Test {
  2.         protected final static ExecutorService pool = Executors
  3.                         .newFixedThreadPool(300);
  4.         private String name="";
  5.          int i=0;
  6.          /**需要测试的方法**/
  7.         public void setName(String name2) {
  8.                 synchronized (name2) {
  9.                         i++;
  10.                         this.name=name2+i;
  11.                         System.out.println(this.name);
  12.                 }
  13.         }
  14.         public static void main(String[] args) {
  15.                 Test test=new Test();
  16.                 for(int i=0;i<100;i++) {
  17.                         pool.execute(new Runnable() {
  18.                                 public void run() {
  19.                                         test.setName("测试");
  20.                                 }
  21.                         });
  22.                 }
  23.         }
  24. }
复制代码

同样可行,而且顺序,无重复
作者: 嘿~~    时间: 2014-10-27 22:42
wzg1015 发表于 2014-10-27 22:23
同样可行,而且顺序,无重复

加我Q2394268935.探讨一下
作者: 嘿~~    时间: 2014-10-27 22:50
第一:name就是private String name = "";作为成员变量的name作为锁匙固定的
第二:可以把锁改为this,那他就是对象test,这个也是唯一的是固定的,那么打印结果也是有序的。
这两种情况是一样的
第三:this.name这个是不固定的。为什么。你第一次调用setName方法后,,在main方法中已经改变了name,
下次再调用,依旧把this.name作为锁,那这个锁就是上次调用setName方法修改后的name值。每个线程都在修改name,因此在main方法中这个name是不固定的。
作者: axing110    时间: 2014-10-29 08:06
支持楼上的说法




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