Java线程同步 - synchronized关键字的放置

时间:2013-12-03 03:32:09

标签: java multithreading

我正在尝试使用synchronized关键字同步线程应用程序。它有时很奇怪。关键字synchronized的放置存在歧义。代码如下:

class Athread implements Runnable
{
    public void run() {

            System.out.println("Starting Implementation of Class Athread");
            for(int i=1;i<=10;i++)
            {
                System.out.println("Class Athread :"+i);
            }
            System.out.println("Ending Implementation of class Athread");
    }
}

class Bthread implements Runnable
{
    public void run() {

            System.out.println("Starting Implementation of Class Bthread");
            for(int i=11;i<=20;i++)
            {
                System.out.println("Class Bthread :"+i);
            }
            System.out.println("Ending Implementation of class Bthread");
    }
}

public class ThreadDemo {
    public static void main(String[] args) {
        System.out.println("Program starts..");

        Athread t1 = new Athread();
        Thread th1 = new Thread(t1);


        Bthread t2 = new Bthread();
        Thread th2 = new Thread(t2);

        synchronized(th1){
            th1.start();
        }
        synchronized(th2){
            th2.start();
        }

        System.out.println("Program ends...");
    }
}

当我将同步块放在我的线程的开头时,它应该锁定该线程而不与其他线程交错。可悲的是,产量不如预期。我的输出如下:

Program starts..
Program ends...
Starting Implementation of Class Athread
Starting Implementation of Class Bthread
Class Athread :1
Class Bthread :11
Class Athread :2
Class Bthread :12
Class Athread :3
Class Bthread :13
Class Athread :4
Class Bthread :14
Class Athread :5
Class Bthread :15
Class Athread :6
Class Bthread :16
Class Athread :7
Class Bthread :17
Class Athread :8
Class Bthread :18
Class Athread :9
Class Bthread :19
Class Athread :10
Class Bthread :20
Ending Implementation of class Athread
Ending Implementation of class Bthread

即使我在类的run()方法中使用synchronized关键字,我也没有得到实际所需的输出。

任何人都可以向我解释一下如何将synchronized关键字应用于上面的示例。

感谢。

更新

在上面的问题中,我错误地理解了同步的概念。根据收到的评论,我试图调用 两个不同的线程并访问两个不同的资源 。但是应该在共享/公共资源上进行同步。因此,应该有一个共同的位置,我应该尝试同步。

5 个答案:

答案 0 :(得分:2)

您所做的是,您在线程开始时同步了一段代码。那时只有主要的方法被执行,所以把synchronized块你没有实现任何东西。

第二件事是你在2个不同的对象上创建了2个线程,因此两个线程都没有相互干扰,因此在运行或同步run方法中放置synchronized块不会做任何不同的事情。

我不知道你想要实现什么,但我修改了'synchronized'示例的代码。

class MyClass implements Runnable{
    public void run() {
            System.out.println(this);
            System.out.println("Starting Implementation of "+Thread.currentThread().getName());
            synchronized(this){
                for(int i=1;i<=10;i++){
                    System.out.println("Class  :"+Thread.currentThread().getName()+" "+i);
                }
            }
            System.out.println("Ending Implementation of "+Thread.currentThread().getName());
    }
}


public class ThreadDemo {
    public static void main(String[] args) {
        System.out.println("Program starts..");

        MyClass obj = new MyClass();
        Thread th1 = new Thread(obj);
        Thread th2 = new Thread(obj);
        th1.setName("Athread");
        th2.setName("BThread");
        th1.start();
        th2.start();

        System.out.println("Program ends...");
    }
}

答案 1 :(得分:1)

synchronized用于同步一段代码,这是一个关键区域,您只希望一个线程在某个时间点进行操作。例如,您的余额金额在银行。

现在,首先,你要创建两个不同类的线程,不知道为什么你会在这里做。 其次,您没有使用类中的任何资源进行同步。

第三,请在正在创建的线程的类中使用synchronize。

答案 2 :(得分:0)

我不确定在ex.business方法的用户定义方法中是否正确地将同步块放在run()方法中的正确方法...

以及为什么在循环中使用相同的变量'i'?也许这会引起一些关于增值的问题。

答案 3 :(得分:0)

如果按照所需的输出表示AthreadBthread开始之前完成,那么您选择的同步是错误的。

Synchronize有2个thinsg来理解:

    如果在同一个对象上进行同步,则
  1. 线程会相互阻塞
  2. 在不同对象上的synchronized块中运行的线程不会相互阻塞。
  3. 现在,在您的代码中,您将围绕对start方法的调用进行同步。因此实际上每个start方法调用都是同步的。但您需要的是一种同步Athread和Bthread的运行方法的机制。

    要修复此问题,请在运行方法中添加同步块,以便在同一对象上进行同步。下面给出一个例子。

    Object lockObject = new Object();
    
    class Athread implements Runnable
    {
        public void run() {
            synchronized(lockObject){
                System.out.println("Starting Implementation of Class Athread");
                for(int i=1;i<=10;i++)
                {
                    System.out.println("Class Athread :"+i);
                }
                System.out.println("Ending Implementation of class Athread");
            }
        }
    }
    
    class Bthread implements Runnable
    {
        public void run() {
            synchronized(lockObject){
                System.out.println("Starting Implementation of Class Bthread ");
                for(int i=1;i<=10;i++)
                {
                    System.out.println("Class Bthread :"+i);
                }
                System.out.println("Ending Implementation of class Bthread ");
            }
        }
    }
    

    您也可以使用synchronized(lockObject)代替synchronized(ThreadDemo.class)。这个想法是bpoth synchronized块应该在同一个对象上同步。多数民众赞成。

答案 4 :(得分:0)

synchronized(foo) { do stuff }意味着,当您正在做的事情时,您可以独占访问对象foo。你愿意等待它。一个很好的例子可能是银行账户。当我向我的银行帐户存款时,没有其他人可以访问它。但是,另一个线程完全能够同步和访问您的银行帐户或储蓄帐户。

在你的例子中,你需要一个共同的对象让两个线程“战斗”。一种解决方案是创建任何类型的第三个对象(非null!)。说一句static Object lockOnMe = new Object();

但是,由于您确实希望对System.out进行独占访问,因此这将是一个更合乎逻辑的选择。当AThread或BThread正在运行时,如果他们在run()方法中同步System.out,则没有其他人可以访问System.out并干扰您的良好输出。

现在,在一个“真正的”应用程序中存在缺点,因为许多线程可能会等待打印,这适用于学习示例。