Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同步线程方法正在并发执行-为什么?_Java_Multithreading - Fatal编程技术网

Java 同步线程方法正在并发执行-为什么?

Java 同步线程方法正在并发执行-为什么?,java,multithreading,Java,Multithreading,我有一个关于线程的问题。我有以下线程类和创建2个线程对象 public class MyThread extends Thread{ String name=""; public MyThread(String string) { name=string; } @Override public void run() { callMe(); } synchronized priva

我有一个关于线程的问题。我有以下线程类和创建2个线程对象

public class MyThread extends Thread{

    String name="";

    public MyThread(String string) {
        name=string;
    }    

    @Override
    public void run() {
        callMe();
    }       

    synchronized private void callMe() {
        System.out.println("Started");
        for (int i = 1; i <= 5; i++) {
            System.out.println(name+" = "+i);
        }           
    }


    public static void main(String[] args) {            
        MyThread a = new MyThread("A");
        MyThread b = new MyThread("B");

        a.start();
        b.start();
    }       
}
我知道A和B是随机打印的,因为线程调度程序会选择它


但我的问题是:为什么不一个接一个地执行循环?我使用了
synchronized
关键字。

每个对象的同步工作。要跨实例同步,您需要一个共享对象进行同步

private final static Object globalLock=new Object();
//后来
私有无效callMe(){
已同步(全局锁定){
System.out.println(“已启动”);

对于(inti=1;i,因为两个线程通过两个不同的对象执行

好的,您现在必须已经从其他答案中认识到了。您正在创建两个单独的对象,即a和b。现在,当您调用start方法时,将通过相应的run方法启动一个新线程以执行(单独的不是相同的)对象。同步确实在方法上,但正好有一个线程通过a的callMe方法运行,正好有一个线程通过b的callMe方法运行。因此,您希望输出应该是:

A-1 A-2 A-3

这是不可能的


希望这有助于

您的
同步
方法有效:

private void callMe() {
    synchronized(this) {
        System.out.println("Started");
        for (int i = 1; i <= 5; i++) {
            System.out.println(name+" = "+i);
        }
    }
}
然后您将得到如下输出:

public final class DemoRunnable implements Runnable {
    @Override
    public synchronized void run() {
        System.out.println("Started");
        for (int i = 1; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " = " + i);
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new DemoRunnable();
        Thread a = new Thread(runnable, "A");
        Thread b = new Thread(runnable, "B");
        a.start();
        b.start();
    }
}
Started
A = 1
A = 2
A = 3
A = 4
A = 5
Started
B = 1
B = 2
B = 3
B = 4
B = 5
(当然,这可能是另一种情况。)

我们仍然有两个线程,但它们在同一个对象上调用同步方法(在本例中是a
demorunable
),因此其中一个线程必须等待另一个线程完成

有几点:

  • 实现
    Runnable
    通常比扩展
    线程更可取;它更灵活
  • 线程
    对象上进行同步有其自身的问题,因为
    线程
    类自己做;请尽量避免
  • 就我个人而言,无论如何我都不喜欢在
    这个
    上同步-我通常会有一个类型为
    Object
    的私有final变量来表示一个只有我的代码才知道的监视器…这样我就可以很容易地看到所有可以在上面同步的代码,这就更容易进行推理

您的代码与此代码相同

private void callMe(){
已同步(此){
System.out.println(“已启动”);

对于(inti=1;i-1从我这里-这是一个非常简洁的答案。没有足够的信息来解释问题发生的原因。好吧,好吧,我将详细说明:)globalLock必须是强制静态的。否则它就不能正常工作?使用静态对象(而不是实例对象)的原因因此,每个实例都在同一个对象上同步。我建议将
globalLock
声明为显式
private
,也声明为
final
。因此,在第一个代码段中,它不会保持同步
方法
对吗?它将变为同步
语句
。第二个代码段是exaSynchronized
方法的示例
我说得对吗?@ninappingale:是的,但这种差异实际上是不相关的-一个
Synchronized
方法实际上是一个普通方法,带有一个包含方法主体的
Synchronized(this)
语句。(例如方法;对于静态方法,它在
对象上同步。)
Started
A = 1
A = 2
A = 3
A = 4
A = 5
Started
B = 1
B = 2
B = 3
B = 4
B = 5
 private void callMe(){
       synchronized(this){
           System.out.println("Started");
           for (int i = 1; i <= 5; i++) {
              System.out.println(name+" = "+i);
           }
       }                           
 }
private void callMe(){
   synchronized(MyThread.class){
     System.out.println("Started");
     for (int i = 1; i <= 5; i++) {
          System.out.println(name+" = "+i);
     }
   }  
}