2017-04-02 103 views
0

我现在正在学习Java并发。我碰到一段代码来这样的:为什么我的同步方法锁定不同的对象?

package pac1; 

import java.util.*; 
import java.util.concurrent.*; 

class A1 { 
    public void f() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("f()"); 
     } 
    } 
} 

class B1 { 
    public void g() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("g()"); 
     } 
    } 
} 

class C1 { 
    public void p() { 
     synchronized (this) { 
      for (int i = 0; i < 5; i++) 
       System.out.println("p()"); 
     } 
    } 

} 

public class V { 
    public static void main(String[] args) { 
     A1 a = new A1(); 
     B1 b = new B1(); 
     C1 c = new C1(); 
     new Thread() { 
      public void run() { 
       a.f(); 
      } 
     }.start(); 
     new Thread() { 
      public void run() { 
       c.p(); 
      } 
     }.start(); 
     b.g(); 
    } 

} 

由于该代码使用不同的对象调用同步方法,我认为它不会妨碍他们互相干扰。但是,结果如下:

​​

BTW,结果是一样的使用锁:

package pac1; 

import java.util.*; 
import java.util.concurrent.*; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

class A { 
    Lock lock = new ReentrantLock(); 

    public void f() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("f()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

class B { 
    Lock lock = new ReentrantLock(); 

    public void g() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("g()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

class C { 
    Lock lock = new ReentrantLock(); 

    public void p() { 
     lock.lock(); 
     try { 
      for (int i = 0; i < 5; i++) 
       System.out.println("p()"); 
     } finally { 
      lock.unlock(); 
     } 
    } 
} 

public class Ex16 { 

    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
     C c = new C(); 
     new Thread() { 
      public void run() { 
       a.f(); 
      } 
     }.start(); 
     new Thread() { 
      public void run() { 
       c.p(); 
      } 
     }.start(); 
     b.g(); 
    } 

} 
+0

尝试打印更多的东西。我猜想Java在创建第二个线程的时候会运行第一个线程的方法,然后在真正开始运行主要方法之前,所以你可以按照1,3,2的顺序打印它们。我敢打赌,如果你做了1000人,他们会混在一起。 – gandaliter

+0

是什么让你觉得他们互相干扰?在每次迭代时向Thread.sleep(500)添加一个调用。 –

回答

0

其实环路根本没有足够长的时间,因此允许线程在同一顺序完成他们已启动。为了说明线程不会干扰,您可以尝试以下方法之一:

  • 使循环运行更长时间,例如, 1000次迭代应该更多的则不够:

    synchronized (this) { for (int i = 0; i < 1000; i++) System.out.println("f()"); }

  • 暂停环路内的线程,但一定要为每个循环设置不同的时间间隔:

    synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println("p()"); try { Thread.sleep(3000); } catch (final InterruptedException ex) { // Swallow } } }

这么久故事短小:这些锁实际上不会干涉。

1

您不需要锁定或在此同步。 Sychronized用于锁定对共享可变状态的访问。你没有任何共享的可变状态开始。

这里有3个线程,没有人可以预测这些线程由于上下文切换而运行的顺序。我没有看到问题。

相关问题