英文:
AtomicLong in Multithreading
问题
public class Account implements Runnable {
private final AtomicLong amount = new AtomicLong(0);
public Account(long difference) {
amount.set(difference);
}
public void run() {
System.out.println("The Balance is : " + amount);
}
}
public class Examples {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 100).forEach(i -> service.submit(new Account(i)));
}
}
I tried to use Read/Write Lock and block level synchronization but no luck. Could please someone spot where am doing mistake?
I output has to be starts from 0,1,2...99.
英文:
I'm trying to use AtomicLong in Multi Threading Environment. My desired result is not working,
public class Account implements Runnable {
private final AtomicLong amount = new AtomicLong(0);
public Account(long difference) {
amount.set(difference);
}
public void run() {
System.out.println("The Balance is : " + amount);
}
}
public class Examples {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 100).forEach(i -> service.submit(new Account(i)));
}
}
I tried to use Read/Write Lock and block level synchronization but no luck. Could please someone spot where am doing mistake?
I output has to be starts from 0,1,2...99.
答案1
得分: 4
没有数据在任何线程之间共享...每个线程都创建自己的AtomicLong
,没有共享。即使它被共享了,也不能保证数字会按顺序打印出来。甚至不能保证所有的数字都会被打印出来(有些数字可能会被打印多次)。
如果我将您的代码更改如下:
public static class Account implements Runnable {
private static final AtomicLong amount = new AtomicLong(0);
public Account(long difference) {
amount.set(difference);
}
public void run() {
System.out.println("The Balance is : " + amount);
}
}
这是我得到的输出示例:
The Balance is : 2
The Balance is : 2
The Balance is : 2
The Balance is : 4
The Balance is : 5
The Balance is : 6
The Balance is : 7
The Balance is : 8
The Balance is : 9
The Balance is : 9
原因是以下情景是可能的:
- 主线程创建
Account(0)
。这将0
写入共享的AtomicLong
。 Thread-0
启动- 主线程创建
Account(1)
。这将1
写入共享的AtomicLong
。 Thread-0
打印值,现在是1
。在这种情况下,0
永远不会被打印出来。
AtomicLong
唯一保证的是对值的所有写入始终对所有在之后进行读取的线程可见。
原子变量的属性在Java文档中有详细说明(请参见这里)。
英文:
There's no data shared between any of your threads... each creates its own AtomicLong
, no sharing. Even if it was shared there would be no guarantee at all that the numbers will print in order. They would not even be a guarantee that all numbers are printed (some of them could be printed more than once).
If I change your code like this:
public static class Account implements Runnable {
private static final AtomicLong amount = new AtomicLong(0);
public Account(long difference) {
amount.set(difference);
}
public void run() {
System.out.println("The Balance is : " + amount);
}
}
Here's an example of output I get:
The Balance is : 2
The Balance is : 2
The Balance is : 2
The Balance is : 4
The Balance is : 5
The Balance is : 6
The Balance is : 7
The Balance is : 8
The Balance is : 9
The Balance is : 9
The reason is that the following scenario is possible:
- main thread creates
Account(0)
. This writes0
to the sharedAtomicLong
., Thread-0
starts up- main thread creates
Account(1)
. This writes1
to the sharedAtomicLong
. Thread-0
prints the value, it's now1
. In this case0
will never be printed.
The only thing that AtomicLong
does guarantee you is that all the writes to the value will always be visible by all threads making a read afterwards.
The properties of atomic variables are detailed in the javadoc (see here).
答案2
得分: 0
也许您的意思是这样的:
public class Account implements Runnable {
private final static AtomicLong seq = new AtomicLong(0);
private final long amount;
public Account() {
amount = seq.getAndIncrement();
}
public void run() {
System.out.println("余额为:" + amount);
}
}
public class Examples {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 100).forEach(i -> service.submit(new Account()));
}
}
这将确保每个账户都获得唯一的`amount`值,但这些值可能以不同的顺序打印出来。
英文:
Maybe you meant something like that:
public class Account implements Runnable {
private final static AtomicLong seq = new AtomicLong(0);
private final long amount;
public Account() {
amount = seq.getAndIncrement();
}
public void run() {
System.out.println("The Balance is : " + amount);
}
}
public class Examples {
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0, 100).forEach(i -> service.submit(new Account()));
}
}
This will guarantee that each account will get a unique value of amount
, but the values could be printed in different order.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论