operate是原子操作,这个操作会在aerospike执行里面代码的时候采用单线程处理
下面两个代码说明原子操作的安全性
案例1:不采用operate
public static void main(String[] args) throws InterruptedException {
// 创建Aerospike客户端(单例,多线程共享)
AerospikeClient client = new AerospikeClient(HOST, PORT);
// 线程数量(模拟10个并发请求)
int threadCount = 10;
CountDownLatch latch = new CountDownLatch(threadCount);
System.out.println("开始执行" + threadCount + "个线程并发操作...");
// 创建并启动多个线程
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
try {
int currentValue;
if(client.exists(null, key)){
currentValue = 1;
}
else {
Bin bin = new Bin(BIN_NAME, "");
client.put(null, key, bin);
currentValue = 0;
}
System.out.println("线程" + threadId + " - currentValue: " + currentValue);
} catch (Exception e) {
System.err.println("线程" + threadId + "执行失败: " + e.getMessage());
} finally {
latch.countDown(); // 线程完成,计数器减1
}
}).start();
}
// 等待所有线程执行完成
latch.await();
System.out.println("所有线程执行完毕");
// 关闭客户端
client.close();
}
}
结果如下图
这是因为非operate包装的操作,存在多线程并发问题,同时访问as去判断有没有这个key,就会存在线程1判断没有这个key然后往里put中,还未完全put完成,线程2~9也来了进行client.exists(null, key),而此时还未完全put完成,所以他们返回的结果都是0
案例2:采用operate操作
public static void main(String[] args) throws InterruptedException {
// 创建Aerospike客户端(单例,多线程共享)
AerospikeClient client = new AerospikeClient(HOST, PORT);
// 线程数量(模拟10个并发请求)
int threadCount = 10;
CountDownLatch latch = new CountDownLatch(threadCount);
System.out.println("开始执行" + threadCount + "个线程并发操作...");
// 创建并启动多个线程
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
try {
// 每个线程执行operate操作
Key key = new Key(AS_NAMESPACE, SET_NAME, UNIQ_KEY);
Bin bin = new Bin(BIN_NAME, 1);
// 执行原子操作:add+get
Record record = client.operate(null, key,
Operation.add(bin),
Operation.get(BIN_NAME));
// 获取当前值并打印
int currentValue = record.getInt(BIN_NAME) == 1 ? 0 : 1;
System.out.println("线程" + threadId + " - currentValue: " + currentValue);
} catch (Exception e) {
System.err.println("线程" + threadId + "执行失败: " + e.getMessage());
} finally {
latch.countDown(); // 线程完成,计数器减1
}
}).start();
}
// 等待所有线程执行完成
latch.await();
System.out.println("所有线程执行完毕");
// 关闭客户端
client.close();
}
}
结果如下图
而operate封装的方法会将add和get都用单线程按顺序去执行(原子操作),而其他的线程来了也要执行这个代码就会等待,这样,就解决了多线程并发问题