
什么是线程安全性?读写数据需要线程隔离,这不会导致数据丢失和不一致,并且每次修改数据都不应将其覆盖.
银行提款的经典示例. 帐户A最初为0,线程A读取0,然后保存100(数据尚未写入),线程B读取0,也保存100. 我们看到的是余额100. 这是不科学的,这是称为线程不安全. 因此,我们必须控制存取对象,让我们锁定数据操作的对象,并在其他线程可以实现线程安全之前更新数据.


这一次我们证明HashSet,我们知道Set接口已实现. Set的特点是不会重复存储的数据. 因为它将首先读取内部保存的数据(如果存在),如果不存储它,否则将被存储. 换句话说,数据存储操作分为两个步骤,首先读取,然后写入. 假设它不是线程安全的,则可能发生的情况是线程安全问题代码,当线程A确定设置的对象不具有元素并将要插入该元素时,线程B也会确定该元素在其中不存在. 对象,也可以插入. 结果将插入两个相同的元素.

我们设计了这样的演示:
class TestHashSet implements Runnable{
// 实现Runnable 让该集合能被多个线程访问
Set<Integer> set = new HashSet<Integer>();
// 线程的执行就是插入5000个整数
@Override
public void run() {
for (int i = 0;i < 5000;i ++) {
set.add(i);
}
}
}

我们在主线程上进行测试:
TestHashSet run2 = new TestHashSet();
// 实例化两个线程
Thread t6 = new Thread(run2);
Thread t7 = new Thread(run2);
// 启动两个线程
t6.start();
t7.start();
// 当前线程等待加入到调用线程后
t6.join();
t7.join();
// 打印出集合的size
System.out.println(run2.set.size());

大多数打印结果是预期的5000,但偶尔会超过5000. 这导致了前面提到的情况线程安全问题代码,证明HashSet不是线程安全的类.
实际上,通过查看源代码,可以发现HashSet使用HashMap在内部维护数据. 根本原因是HashMap不是线程安全的类. 这导致HashSet的非线程安全. 有关Java集合的更多知识,请关注[PHP中文网: java视频]
最后,一个完整的代码案例验证:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* 验证HashSet不是线程安全
*/
public class HashSetTest {
public static void main(String[] args) {
final Set<Integer> set = new HashSet<>();// 结果可能大于1000
// final Set<Integer> set = Collections.synchronizedSet(new HashSet<>());// 结果等于1000
// final Set<Integer> set = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());// 结果等于1000
// 往set写入1-1000
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 1; i <= 1000; i++) {
set.add(i);
}
}
};
int threadNum = 10;// 线程数
List<Thread> threadList = new ArrayList<>();
for (int i = 0; i < threadNum; i++) {
Thread thread = new Thread(runnable);
threadList.add(thread);
thread.start();
}
// 主线程等待子线程执行完成
for (Thread thread : threadList) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(set.size());// 结果可能大于1000
}
}
以上哈希集线程安全吗? (详细的代码验证)有关更多详细信息,请关注php中文网络上的其他相关文章!
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-228274-1.html
可能是思维错了