线程之间的不公平同步
我有这样的代码模式:
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
public class TestRunner {
public static final Object lockObject = new Object();
public static final AtomicInteger counter1 = new AtomicInteger();
public static final AtomicInteger counter2 = new AtomicInteger();
public static class Runner1 implements Runnable {
private volatile boolean running = true;
@Override
public void run() {
while (running) {
synchronized (lockObject) {
counter1.getAndIncrement();
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
// Thread.yield();
}
}
public void stop() {
running = false;
}
}
public static class Runner2 extends TimerTask {
@Override
public void run() {
synchronized (lockObject) {
counter2.getAndIncrement();
}
}
}
public static void main(String[] args) throws Exception {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
Thread thread1 = new Thread(runner1);
Timer timer = new Timer();
timer.scheduleAtFixedRate(runner2, 0, 10);
thread1.start();
Thread.sleep(10000);
timer.cancel();
runner1.stop();
int runner1Percent = (counter1.get()*100 /(counter1.get()+counter2.get()));
System.out.println("No of times Runner1 got called: " + counter1.get());
System.out.println("No of times Runner2 got called: " + counter2.get());
System.out.println("Percentage Runner1 acquire the lock: " + runner1Percent);
System.out.println("Percentage Runner2 acquire the lock: " + (100-runner1Percent));
}
}
我运行此代码大约 10 秒,这是输出:
No of times Runner1 got called: 877
No of times Runner2 got called: 10
Percentage Runner1 acquire the lock: 98
Percentage Runner2 acquire the lock: 2
如此处所示,Thread1 能够获取 98% 的锁,而计时器仅 能够获取锁2%。
如果我取消注释 Thread.yield() 语句并重新运行它,输出 显示:
No of times Runner1 got called: 858
No of times Runner2 got called: 1001
Percentage Runner1 acquire the lock: 46
Percentage Runner2 acquire the lock: 54
这表明Thread1和Timer更均匀地共享锁。这是否意味着 jvm 有一些优化/缓存,以便 Thread1 能够继续获取锁?如果由于其他一些限制我无法替换同步块,那么 Thread.yield() 是否是让线程更均匀地共享锁的正确方法?
任何建议都会有帮助。
I have a code pattern like this:
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
public class TestRunner {
public static final Object lockObject = new Object();
public static final AtomicInteger counter1 = new AtomicInteger();
public static final AtomicInteger counter2 = new AtomicInteger();
public static class Runner1 implements Runnable {
private volatile boolean running = true;
@Override
public void run() {
while (running) {
synchronized (lockObject) {
counter1.getAndIncrement();
try {
Thread.sleep(10);
} catch (Exception e) {
}
}
// Thread.yield();
}
}
public void stop() {
running = false;
}
}
public static class Runner2 extends TimerTask {
@Override
public void run() {
synchronized (lockObject) {
counter2.getAndIncrement();
}
}
}
public static void main(String[] args) throws Exception {
Runner1 runner1 = new Runner1();
Runner2 runner2 = new Runner2();
Thread thread1 = new Thread(runner1);
Timer timer = new Timer();
timer.scheduleAtFixedRate(runner2, 0, 10);
thread1.start();
Thread.sleep(10000);
timer.cancel();
runner1.stop();
int runner1Percent = (counter1.get()*100 /(counter1.get()+counter2.get()));
System.out.println("No of times Runner1 got called: " + counter1.get());
System.out.println("No of times Runner2 got called: " + counter2.get());
System.out.println("Percentage Runner1 acquire the lock: " + runner1Percent);
System.out.println("Percentage Runner2 acquire the lock: " + (100-runner1Percent));
}
}
I run this code for about 10 second and here is the output:
No of times Runner1 got called: 877
No of times Runner2 got called: 10
Percentage Runner1 acquire the lock: 98
Percentage Runner2 acquire the lock: 2
As indicated here, Thread1, is able to acquire the lock 98% while the timer, is only
able to acquire the lock 2%.
If I uncomment out the Thread.yield() statement and rerun it, the output
shows:
No of times Runner1 got called: 858
No of times Runner2 got called: 1001
Percentage Runner1 acquire the lock: 46
Percentage Runner2 acquire the lock: 54
This shows that Thread1 and Timer share the lock more uniformly. Does this mean the jvm has some optimization/caching so that Thread1 is able to keep acquiring the lock? If I am not able to replace the synchronized block due to some other restrictions, is Thread.yield() a right approach to have the threads sharing the lock more uniformly?
Any suggestions would be helpful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论