两个线程可以在同一时间点运行两种不同的方法吗?

class A { private synchronized f() { ... ... } private void g() { ... ... } } 

如果线程T1正在运行同步的f(),那么线程t2可以运行g(),它在同一时间点不同步,而T1仍在运行f()吗?

不在同一个A实例上。实例本身就是锁,所以两个方法同时执行两个方法,两个线程需要两个A实例。

是。 两种方法都可以在同一个实例上同时执行。

只有f()被同步。 线程必须获取this.f()的监视器才能执行f()并且每个实例只存在一个监视器。

g()未同步,运行该方法不需要监视器锁定,因此任何线程都可以随时执行g()

“同步方法在执行之前获取监视器(第17.1节)。”

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.3.6

不会。一个呼叫将阻止,直到另一个完成。 原因是方法上的synchronized关键字扩展为在对象的当前实例上同步。 更具体地说,请考虑以下代码:

 private void synchronized f(){
   ...
 }

以上代码的function与以下代码相同:

 private void f(){
   synchronized(this){
     ...
   }
 }

因此,如果您希望对象中的两个方法仅相互同步,则应创建两个锁定对象。 每个方法都应将其所有代码包装在同步(对象)块中,每个方法一个对象。

是的,如果T1和T2分别在不同的A实例上执行fg

如果两个线程在同一个A实例上执行方法,则一次只能执行一个方法。 如果T1先运行,它将获取A实例的锁定,并执行方法f 。 在T1完成执行f之前,线程T2将无法执行方法g 。 或者相反可能发生:T2可以先运行g ,T1在T2完成后才能运行f

通常,两个线程可以在同一时间点运行两个方法; 但是,在您的示例中,在任何给定时刻只有一个线程可能正在运行f()g()

使用synchronized关键字可以更改线程交互。 每个java对象都有一个锁,一个只有一个线程可以在任何给定时间保存的项。 Synchronized是一个命令,它指示线程在执行方法之前获取锁,然后释放它。 在整个方法执行期间保持锁定。

在您的示例中,在任何给定时间只有一个线程将执行f()g() ,因为“其他”线程将轮流等待获取锁定。

当你有两个同一个类的对象时,你有两个锁。 这意味着您可以获得两个线程来同时运行f()g() synchronized关键字,因为线程将抓取不同对象上的锁。 您无法在不删除synchronized关键字的情况下在同一对象上同时执行线程。

对此的正确答案是重新组装者的答案。

运行这个,你会看到。 您还可以通过取消注释/注释样本的相应部分来使用Thread.sleep()而不是无限循环进行测试。

如果代码没有遵循最佳实践,我很抱歉,我的java非常生疏。

 package threadtest; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class ThreadTest { /** * @param args the command line arguments */ public static void main(String[] args) throws IOException { TestClass tc = new TestClass(); // invokes not sync method FirstThreadRunnable ftr = new FirstThreadRunnable(tc); Thread t1 = new Thread(ftr); // invokes the sync method SecondThreadRunnable str = new SecondThreadRunnable(tc); Thread t2 = new Thread(str); t2.start(); t1.start(); System.in.read(); } public static class TestClass { private int callCount = 0; public void notSynchronizedMethod() { System.out.println("notSynchronizedMethod says hello!" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId()); } public synchronized void synchronizedMethod() throws InterruptedException { // Test with the sleep //System.out.println("entering sync method and pausing from thread: " + Thread.currentThread().getId()); //Thread.sleep(5000); // hold the monitor for 5sec //System.out.println("exiting sync method" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId()); // Test with spinning System.out.println("MAKE IT SPIN! from thread: " + Thread.currentThread().getId()); boolean spin = true; while(spin){ } System.out.println("IT STOPPED SPINNING! from thread: " + Thread.currentThread().getId()); } } // invokes the not sync method public static class FirstThreadRunnable implements Runnable { TestClass tester = null; public FirstThreadRunnable(TestClass tester){ this.tester = tester; } @Override public void run() { for(int i = 0; i < 500; i++){ tester.notSynchronizedMethod(); try { Thread.sleep(50); } catch (InterruptedException ex) { Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex); } } } } // invokes the sync method public static class SecondThreadRunnable implements Runnable { TestClass tester = null; public SecondThreadRunnable(TestClass tester){ this.tester = tester; } @Override public void run() { try { // Test with Sleep() //for(int i = 0; i < 5; i++){ // tester.synchronizedMethod(); //} // Test with the spinning tester.synchronizedMethod(); } catch (InterruptedException ex) { Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex); } } } } 

为了技术性和迂实性的利益, 是的 ,两种方法都可以同时输入。 一个在synchronized(this)上被阻塞,非常少,方法进入并运行,它的第一个语句正在执行,并且执行第一个字节代码指令。