java - 同步有什么问题

标签 java multithreading synchronized

代码出了什么问题,我的线程没有同步: 我在下面的示例中具有线程将调用的同步打印方法,但输出仍然显示线程在访问打印方法时未同步。请参阅下面的输出。

主类

public class ExecutorTester {

    public static void main(String[] args) {

        PrinterRunnable pr = new PrinterRunnable();
        ExecutorService excutor = Executors.newFixedThreadPool(20);
        //ExecutorService excutor = Executors.newSingleThreadExecutor(); 
        excutor.submit(pr); 
        excutor.submit(pr); 
        excutor.submit(pr);
        excutor.submit(pr); 
        excutor.submit(pr); 
        excutor.submit(pr);
        excutor.submit(pr); 
        excutor.submit(pr); 
        excutor.submit(pr);

        excutor.shutdown();

        for(int i =0; i<5;i++)
            System.out.println("In Main Thread : "+i);
    }
}

线程类

public class PrinterRunnable implements Runnable {

    @Override
    public void run() {
        for(int i =0; i<5;i++){
            //System.out.println("In Thread class" +i);
            Printer p = new Printer();
            p.print(i);
        }
    }
}

其他类

public class Printer {

    public synchronized void print(int i){
        System.out.println("Entered Thread: "+Thread.currentThread().getId());
        System.out.println("In thread: "+Thread.currentThread().getId()+"count::"+i );
        System.out.println("Exit Thread: "+Thread.currentThread().getId());
    }
}

控制台输出 (见下面线程13和11都进入了!!!)

Entered Thread: 13
Entered Thread: 11
In thread: 11count::0
Exit Thread: 11
Entered Thread: 11
In thread: 11count::1
Exit Thread: 11
In thread: 13count::0
Exit Thread: 13
Entered Thread: 13
In thread: 13count::1
Exit Thread: 13
........
........
........

最佳答案

当关键字synchronized 是方法签名的一部分时,如

public synchronized void print(int i)

那么此同步引用调用此方法的实例。每次您想要打印某些内容时,您都会创建一个新的 Printer 实例。

为了达到预期的效果,您必须在一个公共(public)对象上进行同步。例如,这可以这样实现:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorTester
{
    public static void main(String[] args)
    {
        PrinterRunnable pr = new PrinterRunnable(new Object());
        ExecutorService excutor = Executors.newFixedThreadPool(20);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);
        excutor.submit(pr);

        excutor.shutdown();

        for (int i = 0; i < 5; i++)
            System.out.println("In Main Thread : " + i);
    }
}

class PrinterRunnable implements Runnable
{
    private final Object monitor;

    PrinterRunnable(Object monitor)
    {
        this.monitor = monitor;
    }

    @Override
    public void run()
    {
        for (int i = 0; i < 5; i++)
        {
            // System.out.println("In Thread class" +i);
            Printer p = new Printer(monitor);
            p.print(i);
        }
    }
}

class Printer
{
    private final Object monitor;

    Printer(Object monitor)
    {
        this.monitor = monitor;
    }

    public void print(int i)
    {
        synchronized (monitor)
        {
            System.out.println("Entered Thread: " + 
                Thread.currentThread().getId());
            System.out.println("In thread: " + 
                Thread.currentThread().getId() + " count::" + i);
            System.out.println("Exit Thread: " + 
                Thread.currentThread().getId());
        }
    }
}

但是,当然,这是一个过于务实的草图。在实际应用程序中,您应该仔细考虑要在哪个对象上同步。

关于java - 同步有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32159818/

相关文章:

c - 无锁地将一个值从一个线程传输到另一个线程

java - 同步方法还是使用 spring @transactional?

java - HashMap 排序java

java - 安排任务在每天的特定时间运行

java - 在线程上调用 interrupt() 是否会创建与被中断线程的 happens-before 关系

java - Java中方法、对象、类的同步

java - 为什么我的代码挂起?

Java:在另一个同步对象内同步对象

java - Android中使用聚类算法时如何取marker Tag

java - 以每个可能的顺序排列数组