【问题标题】:Want a code for the difference between synchronized and asynchronized method想要一个关于同步和异步方法之间区别的代码
【发布时间】:2018-10-06 15:55:04
【问题描述】:

我正在尝试设置同步方法和非同步方法之间的区别。我尝试了以下代码

 class Counter {
    private int counter = 10;
    public int getCounter() {
        return counter;
    }

    public synchronized void doIncrementAndDecrement() {
        counter++;
        keepBusy(500);
        counter--;
    }

    public void keepBusy(int howLong) { // (D)
        long curr = System.currentTimeMillis();
        while (System.currentTimeMillis() < curr + howLong)
            ;
    }
}

class MyCounterThread extends Thread {

    Counter c;

    public MyCounterThread(Counter c, String name) {
        // TODO Auto-generated constructor stub
        super(name);
        this.c = c;
        start();
    }

    @Override
    public void run() {
        for (;;) {
            c.doIncrementAndDecrement();
            sleepForSometime();
            System.out.println(c.getCounter());
        }
    }

    public void sleepForSometime() { // (D)
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class UnSynchronizedExapmle {

    public static void main(String[] args) throws InterruptedException {
        Counter c = new Counter();
        MyCounterThread t1 = new MyCounterThread(c, "A");
        MyCounterThread t2 = new MyCounterThread(c, "B");
        MyCounterThread t3 = new MyCounterThread(c, "C");
    }
}

所以上面我有 doIncrementAndDecrement() 同步方法..

所以我希望计数器的值每次都应该是 10。但这不会发生我的输出就像

10
10
11
10
10
10
10
11
10
10
11
10
11
11
10
10
11
10
11
10
10
10
11
10
10
11
10

所以请帮助我为什么会发生这种情况。或者任何解释同步和异步方法之间区别的博客/文章

【问题讨论】:

  • 同步方法是在当前线程中运行的方法。 Java 只支持同步方法。异步方法是在另一个线程或进程中执行的方法,即异步。 Java 不直接支持这一点,但您可以使用库来模拟。

标签: java multithreading


【解决方案1】:

您的 getCounter() 方法未同步。因此,即使一个线程可能会锁定该方法,另一个线程仍然可以访问并打印您的计数器变量

【讨论】:

  • 是的,它神奇地工作......我还有一个疑问......如果我在我的 keepBusy() 方法中编写 Thread.sleep() 会有什么不同......因为两者的输出完全不同案例
  • 您在问题中编写的 keepBusy() 方法是忙循环,这意味着在它执行时,任何其他线程都不太可能有机会运行。这不是推荐的做法。您应该使用 Thread.sleep() 让其他线程有机会运行。看看stackoverflow.com/questions/4911397/what-is-a-busy-loopstackoverflow.com/questions/4479443/…
  • 虽然如果你真的想保持忙碌,你写的循环很好
【解决方案2】:

您的代码没有同步 getCounter 方法,以便 System.out.println 可以输出计数器的内部状态。 synchronized 方法与 synchronized(this) 相同。

【讨论】:

  • 是的,它神奇地工作......我还有一个疑问......如果我在我的 keepBusy() 方法中编写 Thread.sleep() 会有什么不同......因为两者的输出完全不同案例
  • keepBusy 帮助您轻松找到 counter==11 的状态。如果不使用keeyBusy,“counter++”和“counter--”通常会一起运行(速度很快,这个线程通常不会被打断),所以很难找到counter==11的状态。
【解决方案3】:

...如果我在我的 keepBusy() 方法中编写 Thread.sleep() 会有什么不同.. 因为两种情况下的输出完全不同。

它的作用是使keepBusy() 花费很长时间,因此它使getCounter() 等待很长时间。

输出的差异是由于同步导致 getCounter() 无法“看到”处于递增状态的计数器。

我的意思是 Thread.sleep() 和上述 keepBusy() 方法中的 while 循环在线程调度或锁定方面有何不同..

没有区别。


为了记录,一个真正的程序有一个像keepBusy() 这样的方法在同步方法或块中休眠是个坏主意。 sleep 会导致任何其他试图在目标对象上同步的线程被阻塞......这可能会降低应用程序的实际并行度。

【讨论】:

  • 我的意思是 Thread.sleep() 和上述 keepBusy() 方法中的 while 循环在线程调度或锁定方面有何不同...
猜你喜欢
  • 2021-10-16
  • 2015-07-25
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
相关资源
最近更新 更多