我理解AtomicInteger和其他原子变量允许并发访问。在什么情况下通常使用这个类?
当前回答
如果您查看AtomicInteger具有的方法,您将注意到它们倾向于对应于对int的常见操作。例如:
static AtomicInteger i;
// Later, in a thread
int current = i.incrementAndGet();
是线程安全的版本:
static int i;
// Later, in a thread
int current = ++i;
方法映射如下: ++i是i. incrementandget () i++就是i. getandincrement () ——i是i. decrementandget () i——是i. getanddecrement () I = x = I .set(x) X = I = X = I .get()
还有其他方便的方法,如compareAndSet或addAndGet
其他回答
AtomicInteger有两个主要用途:
As an atomic counter (incrementAndGet(), etc) that can be used by many threads concurrently As a primitive that supports compare-and-swap instruction (compareAndSet()) to implement non-blocking algorithms. Here is an example of non-blocking random number generator from Brian Göetz's Java Concurrency In Practice: public class AtomicPseudoRandom extends PseudoRandom { private AtomicInteger seed; AtomicPseudoRandom(int seed) { this.seed = new AtomicInteger(seed); } public int nextInt(int n) { while (true) { int s = seed.get(); int nextSeed = calculateNext(s); if (seed.compareAndSet(s, nextSeed)) { int remainder = s % n; return remainder > 0 ? remainder : remainder + n; } } } ... } As you can see, it basically works almost the same way as incrementAndGet(), but performs arbitrary calculation (calculateNext()) instead of increment (and processes the result before return).
就像gabuzo说的,当我想通过引用传递一个整型时,有时我使用AtomicIntegers。它是一个内置类,具有特定于体系结构的代码,因此它比我可以快速编写的任何MutableInteger更容易,也可能更优化。也就是说,这感觉像是对课程的滥用。
Atomic classes are not general purpose replacements for java.lang.Integer and related classes. They do not define methods such as equals, hashCode and compareTo. (Because atomic variables are expected to be mutated, they are poor choices for hash table keys.) Additionally, classes are provided only for those types that are commonly useful in intended applications. For example, there is no atomic class for representing byte. In those infrequent cases where you would like to do so, you can use an AtomicInteger to hold byte values, and cast appropriately. You can also hold floats using Float.floatToRawIntBits(float) and Float.intBitsToFloat(int) conversions, and doubles using Double.doubleToRawLongBits(double) and Double.longBitsToDouble(long) conversions.
参考:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
compareAndSet()函数的简单示例:
import java.util.concurrent.atomic.AtomicInteger;
public class GFG {
public static void main(String args[])
{
// Initially value as 0
AtomicInteger val = new AtomicInteger(0);
// Prints the updated value
System.out.println("Previous value: "
+ val);
// Checks if previous value was 0
// and then updates it
boolean res = val.compareAndSet(0, 6);
// Checks if the value was updated.
if (res)
System.out.println("The value was"
+ " updated and it is "
+ val);
else
System.out.println("The value was "
+ "not updated");
}
}
打印出来的是: 前值:0 该值被更新为6 另一个简单的例子:
import java.util.concurrent.atomic.AtomicInteger;
public class GFG {
public static void main(String args[])
{
// Initially value as 0
AtomicInteger val
= new AtomicInteger(0);
// Prints the updated value
System.out.println("Previous value: "
+ val);
// Checks if previous value was 0
// and then updates it
boolean res = val.compareAndSet(10, 6);
// Checks if the value was updated.
if (res)
System.out.println("The value was"
+ " updated and it is "
+ val);
else
System.out.println("The value was "
+ "not updated");
}
}
打印出来的是: 前值:0 没有更新该值
我使用AtomicInteger来解决就餐哲学家的问题。
在我的解决方案中,使用AtomicInteger实例来表示fork,每个哲学家需要两个。每个哲学家都被标识为一个整数,从1到5。当一个哲学家使用一个fork时,AtomicInteger保存哲学家的值,从1到5,否则该fork没有被使用,因此AtomicInteger的值为-1。
AtomicInteger允许在一个原子操作中检查一个fork是否空闲,value==-1,如果空闲则将其设置为fork的所有者。参见下面的代码。
AtomicInteger fork0 = neededForks[0];//neededForks is an array that holds the forks needed per Philosopher
AtomicInteger fork1 = neededForks[1];
while(true){
if (Hungry) {
//if fork is free (==-1) then grab it by denoting who took it
if (!fork0.compareAndSet(-1, p) || !fork1.compareAndSet(-1, p)) {
//at least one fork was not succesfully grabbed, release both and try again later
fork0.compareAndSet(p, -1);
fork1.compareAndSet(p, -1);
try {
synchronized (lock) {//sleep and get notified later when a philosopher puts down one fork
lock.wait();//try again later, goes back up the loop
}
} catch (InterruptedException e) {}
} else {
//sucessfully grabbed both forks
transition(fork_l_free_and_fork_r_free);
}
}
}
因为compareAndSet方法不阻塞,它应该增加吞吐量,完成更多的工作。正如你所知道的,Dining Philosophers问题是在需要对资源进行受控访问时使用的,即需要fork,就像一个进程需要资源来继续工作一样。
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?