gpt4 book ai didi

java - 将 Integer 对象用作同步块(synchronized block)中的锁时的潜在并发问题

转载 作者:搜寻专家 更新时间:2023-11-01 01:43:16 25 4
gpt4 key购买 nike

在处理多线程程序时,我观察到非常奇怪的行为。

当 Integer 对象被用作锁时,似乎多个线程可以在同步块(synchronized block)中。甚至认为这不是预期的。

如果我在下面的程序中使用任何其他静态成员,如“s”、“o”和“c”定义,它会按预期工作。

代码-

public class MyThread extends Thread{
private static Integer ii=1; //Works fine
private static Integer i=1;
private static String s="1"; //Works fine
private static Object o= new Object(); //Works fine
private static Class<MyThread> c= MyThread.class; //Works fine

public void run(){
synchronized(i){
System.out.print(i++ +" ");
System.out.print(i+" ");
}
}
public static void main(String[] str) throws InterruptedException{
for(int i=0;i<100;i++){
MyThread t= new MyThread();
t.start();
}
Thread.sleep(100);
System.out.println();
MyThread t= new MyThread();
t.start();t.join();
if(i!=102)
System.out.println("fail");
}
}

输出-

2 3   3 4   5 6   8 9   9 10   10 11 12   12 13   13 14   14 15   16 17   1 17   15 17   12   17 18   18 20   20 21   21 22   7 22 6 23   4 23   23 24   24 25   25 26   23   22   19 27   26 27   27 28   28 29   29 30   30 31   31 32   32 33   33 34   34 35   35 36   36 37   37 38   38 39   39 41   40 41 42   42   42 43   43 44 45   45   45 48   47 48   46 48   48 49   49 50   50 51   51 52   52 53   53 54   54 55   55 56   56 57   57 58   58 59   59 60   60 61   61 62   62 63 64   64 65   64   65 66   66 67   68 69   69 70   67 70   70 71   71 72   72 73   73 75   74 76   75 76   76 77   77 79 80   78 80   80   80 83 84   82 85   85 86   86 87   87 88   88 89   89 90   81 94   93 94   92 94   91 94   90 94   84   94 96   96 98   98 99   84 99   97 99   95 99   99 100   100 101   
101 102

如您所见,当它打印“10 11 12”时,有两个线程在同步块(synchronized block)中执行。

是我做错了什么还是遗漏了什么?

是否与幕后的一些优化有关?因为如果我使用“ii”进行锁定,一切都会完美无缺。

此外,当使用“i”时,它会打印“失败”,但很少。

以下是用于运行程序的java版本。 java -version java version "1.7.0_51"Java(TM) SE Runtime Environment (build1.7.0_51-b13) Java HotSpot(TM) 客户端 VM(构建 24.51-b03,混合模式,共享)

您可以使用下面的程序来运行程序来运行这一堆并查看结果。

public class MyThread extends Thread{
private static Integer ii=1;
private static Integer i=1;
private static String s="1";
private static Object o= new Object();
private static Class<MyThread> c= MyThread.class;

public void run(){
synchronized(ii){
System.out.print(i++ +" ");
System.out.print(i+" ");
}
}
public static void main(String[] str) throws InterruptedException{
for(int j=0;j<100;j++){
for(int i=0;i<100;i++){
MyThread t= new MyThread();
t.start();
}
Thread.sleep(50);
System.out.println();
MyThread t= new MyThread();
t.start();t.join();
if(i!=102)
System.out.println("fail");
Thread.sleep(50);
i=1;
System.out.println();
}
}
}

最佳答案

这个

i++

相当于

i = Integer.valueOf(i.intValue() + 1)

换句话说,i 现在引用了一个不同的对象,与您最初同步的对象不同。

如果一个线程恰好在 i 改变后进入了 synchronized block ,它也会进入,因为它获取了不同对象上的监视器。

Because if I used 'ii' for locking everything works perfectly.

您不会在任何地方更改对 ii 的引用。

关于java - 将 Integer 对象用作同步块(synchronized block)中的锁时的潜在并发问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22047209/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com