public class Service {
       private String lock = "123"; public void test() {
synchronized (lock) {
try {
System.out.println(Thread.currentThread().getName() + " - start;");
                // 在这里改变lock对象
lock = "456 "; Thread.sleep(600);
System.out.println(Thread.currentThread().getName() + " - end;");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}/**
 * main方法
 */
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
ThreadB b = new ThreadB(service);

a.setName("a");
b.setName("b");

a.start();

// 在这里将主线程睡眠一段时间,就会出现不一样的结果?????(请问是为什么)
Thread.sleep(200);

b.start();
}
}/**
 * ThreadA 
 */
class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
this.service = service;
} @Override
public void run() {
super.run(); service.test();
}
}/**
 * ThreadB
 */
class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
this.service = service;
} @Override
public void run() {
super.run(); service.test();
}
}

解决方案 »

  1.   

    因为线程会抢占执行权,需要同步一下(Synchronized)你学到后面就懂了
      

  2.   

    不是很懂,我给test的方法体中加了锁啊,当执行到这段的时候,应该只有一个能执行啊,然后改变锁对象,此时另一个线程应该能运行了啊???
      

  3.   

    因为锁住的是对象的对象头不是引用,private String lock = "123";
    synchronized (lock)这句话其实是锁住的常量池中的"123"对象的对象头
    在A线程中修改了lock = "456 ";
    B线程再次进入synchronized (lock)这个代码块时lock = "456 ",
    发现常量池中的"456"对象没有被锁住,所以还是可以进入synchronized (lock)代码块的
      

  4.   

    呀,昨天没看仔细 你第一次执行的时候两个线程会抢占执行权
    如果第一个抢到了就是a-start反之亦是
    本来b线程也要抢占执行权,但是程序在睡眠
    这个时候改变锁的对象456没有锁住
    b线程肯能又抢到了执行权
    但是因为时间的关系你运行的时候看不出来
    你暂停了的时间就会程序出错的几率更大,也就是你提问的原因
      

  5.   

    synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " - start;");
                    // 在这里改变lock对象
                    lock = "456 ";
    这段有问题的,。一般同步的对象都必须是finally类型的,不变的。
    如果你把他改变了,后面就没有线程可以获取到同步对象了。