实现 CAS(比较和交换)算法的 Java 程序
比较和交换是设计并发算法时使用的一种技术。方法是将变量的实际值与变量的预期值进行比较,如果实际值与预期值匹配,则用变量的实际值替换传入的新值。
算法工作:
就好像我们知道这个变量应该是 1,我们想把它改成 2。由于这是一个多线程环境,我们知道其他人可能正在处理同一个变量。因此,我们应该首先检查变量的值是否如我们所想的是 1,如果是,那么我们将其更改为 2。如果我们现在看到变量是 3,那么这意味着其他人正在处理它,所以我们现在不要碰它。
检查然后行动接近 :-
并发问题最常见的情况是“先检查后行动”的方法。当代码首先检查变量值,然后基于该值进行操作时,就会发生“先检查后操作”的情况。这里有一个简单的例子:
public boolean lock() {
if(!locked) {
lock = true;
return true;
}
return false;
}
上面,伪代码意味着,如果它已经被锁定,你不需要再次锁定。所以你首先检查并且只有在需要的时候,行动。
上面的代码并不安全,因为如果两个或多个线程可以同时访问 lock()函数并进行检查,那么上面的 lock() 函数将不能保证工作,因为所有线程都会锁定资源并将其作为自己的资源使用。
我们细说一下:
存在线程 A 和线程 B ,线程 B 可以在线程 A 已经检查锁定并且看到它是假的之间的任何时间检查锁定,那么线程 A 和线程 B 都可以看到锁定是假的,然后两者都将基于该信息而行动。
上述问题可以通过同步整个代码块来解决。那么一次只有一个线程(线程 A 或线程 B)进行检查并采取行动,只有在进入代码的线程完成检查并采取行动之后,另一个线程才能尝试。现在线程之间不会有误会了。
同步代码示例:
class GFG {
private boolean locked = false;
public synchronized boolean lock() {
if(!locked) {
locked = true;
return true;
}
return false;
}
}
现在 lock()方法是同步的,所以一次只有一个线程可以在同一个 lock()函数上执行它。
原子操作
在 Java 5 之后,我们不再需要用 check and act 代码来实现或编写同步块,Java 5 通过Java . util . concurrent . atomic:提供了这种支持,这是一个用于对单个变量进行无锁、线程安全编程的类工具包。
AtomicBoolean 确保一次只有一个线程可以读取。
下面是一个示例,展示了如何使用原子工具实现 lock()方法:
public static class MyLock {
private AtomicBoolean locked = new AtomicBoolean(false);
public boolean lock() {
return locked.compareAndSet(false, true);
}
}
请注意,锁定的变量不再是一个布尔值,而是一个原子对象。这个类有一个 compareAndSet() 函数,它会将 AtomicBoolean 实例的值与期望值进行比较,如果有期望值,它会用一个新值交换该值。在这种情况下,它将 locked 的值与 false 进行比较,如果为 false,它将 AtomicBoolean 的新值设置为 true。
如果值被交换,compareAndSet()方法返回 true,否则返回 false。
还有很多其他原子变量,比如:
- atomic integer:这个变量可以让你自动更新一个 int 值。
- AtomicLong:Long 具有线程安全的“比较和交换”功能。
- 原子引用: 这个变量提供了一个可以原子读写的对象引用变量。
- *原子闪烁阵列、原子闪烁阵列和原子闪烁阵列*
*原子整数示例:*
Java 语言(一种计算机语言,尤用于创建网站)
// Java Program to demonstrates
// the compareAndSet() function
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");
}
}
**Output
```java Previous value: 0 The value was updated and it is 6
```**
当多个线程试图使用 CAS (比较和交换)算法同时更新同一个变量时,一个线程获胜并更新该变量的值,其余线程失败。但是失败者不会因为挂线而受到惩罚。他们可以自由地重试操作,或者干脆什么也不做。
版权属于:月萌API www.moonapi.com,转载请注明出处