【问题标题】:Java synchronized method usageJava同步方法使用
【发布时间】:2017-07-21 11:45:04
【问题描述】:

我试图掌握 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]

我的代码有什么问题?

【问题讨论】:

  • 尝试使用run() 方法synchronized 而不是inc() 方法。
  • 使用atomic Integer类方法处理线程
  • “我预计对 inc() 方法使用同步会产生顺序递增”为什么您期望它?您只同步了inc 方法。这意味着没有两个线程可以并行执行它,但这并不意味着这将是某种特定的执行顺序。
  • @Konstantin 请找到我的答案
  • @Konstantin 请投票,谢谢。 :)

标签: java concurrency synchronization


【解决方案1】:

请找到正确的代码:-

 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】:

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

    【讨论】:

      【解决方案3】:

      如果线程 2 在线程 1 之后启动,那么更好的解决方案是使用连接方法,这意味着程序将希望在线程 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 文档以阐明同步方法的工作原理 Synchronized Methos

      • 首先,对同一对象的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他为同一对象调用同步方法的线程都会阻塞(暂停执行),直到第一个线程处理完该对象。
      • 其次,当一个同步方法退出时,它会自动与同一对象的任何后续同步方法调用建立起之前的关系。这保证了对象状态的更改对所有线程都是可见的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-15
        相关资源
        最近更新 更多