关于方法同步顺序的讨论

关于方法同步顺序的讨论

问题描述:

在 The JavaTM Virtual Machine Specification CHAPTER 8--- 8.11 Example: Out-of-Order Writes
中 有这么一个例子:

[code="java"]class Simple {
int a = 1, b = 2;
void to() {
a = 3;
b = 4;
}
void fro()
System.out.println("a= " + a + ", b=" + b);
}
}[/code]

文中阐述的大概意思是 如果 方法 to 和fro 不进行同步 那么 两个线程 一个访问to 一个访问fro 结果 a,b有可能出现任意值组合,
我自己写了一个程序模拟这个操作 但是总是不能成功的模拟出 不同步状态下 乱序的结果

以下是我的代码

[code="java"]
public class Simple {
int a = 1, b = 2;
void to() {
a = 3;
b = 4;
}
void from() {
System.out.println(Thread.currentThread().getName()+" a= " + a + ", b=" + b);
}

public static void main(String[] args){
    final Simple a = new Simple();
    Runnable r1 = new Runnable(){
        public void run() {
            a.from();

        }
    };
    Runnable r = new Runnable(){
        public void run() {
            a.to();

        }
    };



    new Thread(r1).start();
    new Thread(r).start();

}

}
[/code]

结果 总是:

Thread-0 a= 1, b=2
如果 调换 执行顺序

new Thread(r).start();
    new Thread(r1).start();

那么结果是:

Thread-1 a= 3, b=4

我的问题是 如何才能模拟出乱序的结果 比如
a =1,b =4
或者
a =3 ,b=2
这样因为没有同步造成的结果不一致现象?

同样的问题 在 Java Concurrency In Practice Chapter 16. The Java Memory Model 中 描述 reording时 的一个DEMO

[code="java"]
public class PossibleReordering {
static int x = 0, y = 0;
static int a = 0, b = 0;
public static void main(String[] args)throws InterruptedException {
Thread one = new Thread(new Runnable() {
public void run() {
a = 1;
x = b;
}
});
Thread other = new Thread(new Runnable() {
public void run() {
b = 1;
y = a;
}
});
one.start();
other.start();
one.join();
other.join();
System.out.println("( "+ x + "," + y + ")");

}
}
[/code]

这段代码在文章中 被当成没有同步的状态,有可能导致多个结果 但是我运行了很多次 都是一个结果:
( 0,1)

因为你的电脑跑的太快了,你在to里sleep一下

[code="java"]
void to() {

a = 3;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}

b = 4;

}

[/code]

分别打印输出,即可,另外from, to里边应该有重新赋值。用用下边的代码:
[code="java"]package mytest.util;

public class Simple
{
int a = 1, b = 2;

void to()
{
    a = 3;
    System.out.print(Thread.currentThread().getName() + " a= " + a + "    ");
    b = 4;
    System.out.println(Thread.currentThread().getName() + " b= " + b);
}

void from()
{
    a = 1;
    System.out.print(Thread.currentThread().getName() + " a= " + a + "    " );
    b = 2;
    System.out.println(Thread.currentThread().getName() + " b= " + b);
}

public static void main(String[] args)
{
    final Simple a = new Simple();
    Runnable r1 = new Runnable()
    {
        public void run()
        {
            a.from();
        }
    };
    Runnable r2 = new Runnable()
    {
        public void run()
        {
            a.to();
        }
    };

    for (int i=0; i<10; i++)
    {
        new Thread(r1).start();
        new Thread(r2).start();
    }
}

}
[/code]

可以试试在 to 方法中,在 a = 3; b = 4; 中间加上 Thread.sleep(50); ,把 两个赋值语句的间隔时间加长。
即:
[code="java"]
void to() {

a = 3;

Thread.sleep(50);
b = 4;

}
[/code]