Java同步方法用法

时间:2017-07-21 11:45:04

标签: java concurrency synchronization

我试图掌握Java中同步方法的概念,但遇到的行为似乎令人困惑,至少对我而言; 在代码中:

public class parallelUpdate
{
    public static void main(String[] args)
    {
        Ob ob = new Ob();
        new Thread(ob).start();
        new Thread(ob).start();
    }
}

class Ob implements Runnable
{
    static int cnt = 0;

    private synchronized void inc()
    {
        cnt++;
    }

    @Override
    public void run()
    {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread());
            inc();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

...两个踏板并行执行递增:

Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]

我预计对inc()方法使用 synchronized 会产生顺序递增,例如:

Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]

我的代码出了什么问题?

3 个答案:

答案 0 :(得分:0)

这是因为线程调度程序决定运行什么线程,并且没有选择线程的特定顺序。您可以在线程上设置优先级,但是由调度程序决定是否选择它。您可以要求调度程序运行特定的线程,但不要强制它。 同步方法保证该方法一次只能由一个线程运行。 我还建议检查Thread Executers API,它提供了创建,维护和销毁线程的更简洁方法。 这是java中线程的有用链接:http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

答案 1 :(得分:0)

请找到正确的代码: -

 public class parallelUpdate {
        public static void main(String[] args) {
            Ob ob = new Ob();
            new Thread(ob).start();
            new Thread(ob).start();

        }
    }


    class Ob implements Runnable {
        static int cnt = 0;
        private synchronized void inc() {
              for (int i = 0; i < 5; i++) {
                  System.out.println(Thread.currentThread());
                  cnt++;
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              } 
        }
        @Override
        public void run() {
          inc();
        }
    }

针对您的代码的说明: -

您正在将 inc(); 方法设为同步,但它们与**for loop**没有同步,因此您的两个步骤进入并执行inc();同步操作。

答案 2 :(得分:0)

如果线程2在线程1之后启动,那么更好的解决方案是使用join方法,这意味着程序将需要直到线程1完成才能启动线程2.

how wait for a thread to finish...

public static void main(String[] args) {
        Ob ob = new Ob();
        Thread myFirstThread = new Thread(ob);
        myFirstThread.start();

        try {
            myFirstThread.join();
        } catch (InterruptedException e) {

            e.printStackTrace();
        }   

        Thread mySecondThread = new Thread(ob);
        mySecondThread.start();

    }

转到java文档以阐明syncrhonized方法的工作原理 Synchronized Methos

  • 首先,对同一对象的两个同步方法的调用不可能进行交错。当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程都会调用同一个对象的同步方法(暂停执行),直到第一个线程完成该对象为止。
  • 其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立一个先发生关系。这可以保证对所有线程都可以看到对象状态的更改。