Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 私有变量是线程安全的吗_Java_Multithreading_Thread Safety_Concurrentmodification - Fatal编程技术网

Java 私有变量是线程安全的吗

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

当两个线程试图修改对象的数据时,开发api(如java中的Collections api)的开发人员是否应该手动抛出ConcurrentModificationException

当多个线程试图修改
人的对象的内容时,为什么这段代码不抛出异常

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