Java 私有变量是线程安全的吗
当两个线程试图修改对象的数据时,开发api(如java中的Collections api)的开发人员是否应该手动抛出ConcurrentModificationException 当多个线程试图修改Java 私有变量是线程安全的吗,java,multithreading,thread-safety,concurrentmodification,Java,Multithreading,Thread Safety,Concurrentmodification,当两个线程试图修改对象的数据时,开发api(如java中的Collections api)的开发人员是否应该手动抛出ConcurrentModificationException 当多个线程试图修改人的对象的内容时,为什么这段代码不抛出异常 public class Main { public static void main(String[] args) { // write your code here RunnableDemo r = new Runnab
人的对象的内容时,为什么这段代码不抛出异常
public class Main {
public static void main(String[] args) {
// write your code here
RunnableDemo r = new RunnableDemo();
for (int i = 0; i < 10; i++) {
Thread t = new Thread(r, "Thread " + i);
t.start();
}
}
}
class RunnableDemo implements Runnable {
private Person person = new Person();
@Override
public void run() {
for (int i = 0; i < 100; i++) {
person.setName("Person" + i);
System.out.println(person.getName());
}
}
}
class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
公共类主{
公共静态void main(字符串[]args){
//在这里编写代码
RunnableDemo r=新的RunnableDemo();
对于(int i=0;i<10;i++){
螺纹t=新螺纹(r,“螺纹”+i);
t、 start();
}
}
}
类RunnableDemo实现Runnable{
私人=新人();
@凌驾
公开募捐{
对于(int i=0;i<100;i++){
person.setName(“person”+i);
System.out.println(person.getName());
}
}
}
班主任{
私有字符串名称;
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
}
当您认为必须抛出异常时,应该抛出异常。当两个线程试图同时修改person对象时,您的代码不会引发异常,但在这种情况下,您可能会得到不可预测的结果,您应该手动阻止并发修改。让我们一次了解这一步。
首先,我将尝试回答几个你可能想到的问题
a)您正在创建多个线程吗?
Ans。可以肯定,您正在创建101个逻辑线程(通过调用线程的start()方法,1个主线程+100个其他线程)。我的逻辑意思是,实际上没有100个并行线程,而是将它们映射到核心内核线程(基本上是核心的数量)
每个核心都有一个工作队列,逻辑线程被分配给核心。可能会发生这样的情况(比如在双核机器中),其中一个核心在处理某个任务时非常繁忙,以至于所有应用程序线程(由您的程序创建)都映射到同一个核心
JVM决定如何映射线程、调度逻辑线程及其执行时间
b)调用start()时会发生什么情况?
答案。有关线程生命周期的准确概述,请访问:
要突出显示,调用start()方法不会使线程处于运行状态。线程调度程序必须拾取它才能进入该状态。因此,并非所有由程序启动的线程都可以并行运行
c)这么说之后这里发生了什么事?
答案。在您的情况下,任务非常小,JVM决定在调度另一个线程之前先释放一个线程。因为根据JVM,如果它不这样做,将在获取和释放CPU资源方面浪费大量时间,因此在上下文切换方面将浪费大量时间
这是你的一般解释
-您在这里理解错了什么?
答案。要获得异常,必须先有人抛出异常。整个代码不会生成异常
您将“name”设置为每个线程的新引用,而不是修改字符串的状态(在JAVA中实际上是不可变的)
当两个线程试图修改对象的数据时,开发api(如java中的Collections api)的开发人员是否应该手动抛出ConcurrentModificationException?
答案。如果状态可以由多个线程修改,并且会影响用户查看数据结构的相应状态(如ArrayList、HashMap等),则无权成为线程安全的API应抛出ConcurrentModificationException如果希望类抛出ConcurrentModificationException
,则必须编写抛出它的代码
Java不会抛出ConcurrentModificationException
,因为两个线程试图同时更新同一对象。事实上,Java从不抛出ConcurrentModificationException
一些标准Java库类在注意到对象处于坏状态时抛出该异常,这可能是由于调用方违反规则造成的
例如,某些容器类的Javadoc表示,在对容器进行迭代时,不允许修改容器。如果代码获得迭代器,然后更新容器,然后调用iterator.next()
,next()
调用将在注意到容器不再处于与创建迭代器时相同的状态时抛出ConcurrentModificationException
这种情况下的抛出是明确的。它不是出自Java的核心:它位于容器类的源代码中。如果查看该类的源代码,您将看到如下内容:
public T next() {
if (...the container has been modified...) {
throw new ConcurrentModificationException(...);
}
...
}
如果希望类抛出该异常,则必须编写一些类似的代码
/*
* Thread-Safe Example in Java
*/
public class Counter {
private int count;
AtomicInteger atomicCount = new AtomicInteger( 0 );
/*
* This method thread-safe now because of locking and synchornization
*/
public synchronized int getCount(){
return count++;
}
/*
* This method is thread-safe because count is incremented atomically
*/
public int getCountAtomically(){
return atomicCount.incrementAndGet();
}
}
阅读更多信息:请看下面的答案:它不会引发异常,因为您从未让它检测/引发异常ConcurrentModificationException
并不是神奇的-就像其他所有异常一样,当/如果您决定应该抛出它,您实际上必须抛出它。因此,不允许您的类实例被多个线程修改是开发人员的工作吗?大多数(a)、(b)和(c)都是无关的,并且依赖于实现。我会把它全部移除。唯一相关的部分是在第一个“An”之后的集合趋势,即“逻辑线程”,您正在使用该答案跨越多个抽象层次。问题在于Java,而不是计算机体系结构。Th