我想测量2个线程计数到1000的时间。我如何对以下代码进行基准测试?
public class Main extends Thread {
public static int number = 0;
public static void main(String[] args) {
Thread t1 = new Main();
Thread t2 = new Main();
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
for (int i = 0; i <= 1000; i++) {
increment();
System.out.println(this.getName() + " " + getNumber());
}
}
public synchronized void increment() {
number++;
}
public synchronized int getNumber() {
return number;
}
}
即使我使用synchronized
关键字,为什么我仍然会得到以下结果(摘录)?
Thread-0 9
Thread-0 11
Thread-0 12
Thread-0 13
Thread-1 10
答案 0 :(得分:1)
输出未同步。场景是:
10
。10
调用println。答案 1 :(得分:1)
你没有同步这个:
for (int i = 0; i <= 1000; i++) {
increment();
System.out.println(this.getName() + " " + getNumber());
}
因此,一个线程可以执行increment()
,等待下一个线程,然后保持getValue()
(从而得到你的结果)。考虑到添加值的速度有多快,更改线程会为多次迭代提供另一个时间。
待办事项 public static final String LOCK =“lock”;
synchronized(LOCK) {
for (int i = 0; i <= 1000; i++) {
increment();
System.out.println(this.getName() + " " + getNumber());
}
}
方法不需要synchronize
(正如我在评论中解释的那样)。
答案 2 :(得分:1)
为什么我仍然得到以下结果(摘录),即使我使用synchronized关键字?
您同步对number
变量的访问权限,但是增量和获取是分开同步的,这也不会使您的println()
原子。这个序列是完全可能的:
0 -> inc
1 -> inc
0 -> getnumber
1 -> getnumber
1 -> print
0 -> print
首先,如果您想解决“增量和获取”问题,可以使用AtomicInteger
:
private static final AtomicInteger count = new AtomicInteger(0);
// ...
@Override
public void run()
{
final String me = getName();
for (int i = 0; i < 1000; i++)
System.out.println(me + ": " + count.incrementAndGet());
}
但是,即使这样也不能保证打印顺序。使用上面的代码,这种情况仍然可能:
0 -> inc
0 -> getnumber
1 -> inc
1 -> getnumber
1 -> print
0 -> print
要解决此问题,您需要使用例如ReentrantLock
:
private static final Lock lock = new ReentrantLock();
private static int count;
// ...
@Override
public void run()
{
final String me = getName;
for (int i = 0; i < 1000; i++) {
// ALWAYS lock() in front of a try block and unlock() in finally
lock.lock();
try {
count++;
System.out.println(me + ": " + count);
finally {
lock.unlock();
}
}
}
答案 3 :(得分:1)
你没有同步。 synchronized
关键字相当于synchonize (this) {}
,但您增加的static
数字不包含在您的对象中。你实际上有2个对象/线程,它们都与自己同步,而不是彼此同步。
要么设置属性volatile
并且根本不进行同步,要么像这样使用锁定对象:
public static int number = 0;
public static final Object lock = new Object();
public void increment() {
synchronized (lock) {
number++;
}
}
public int getNumber() {
synchronized (lock) {
return number;
}
}