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_Synchronized - Fatal编程技术网

Java 此代码中是否存在竞争条件?

Java 此代码中是否存在竞争条件?,java,multithreading,thread-safety,synchronized,Java,Multithreading,Thread Safety,Synchronized,我需要在5个线程中增加一个计数器,直到它达到500。像这样的5个线程正在工作。但我需要知道它是否有比赛条件 这个代码的另一个问题是它给我的打印顺序错误 class HiloContador extends Thread { static int count = 0; @Override public void run() { for (int i = 0; i < 100; i++) { synchronized (new

我需要在5个线程中增加一个计数器,直到它达到500。像这样的5个线程正在工作。但我需要知道它是否有比赛条件

这个代码的另一个问题是它给我的打印顺序错误

class HiloContador extends Thread {

    static int count = 0;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (new Integer(count)) {
                ++count;
                System.out.println(count);
            }
        }
    }
}
类HiloContador扩展线程{
静态整数计数=0;
@凌驾
公开募捐{
对于(int i=0;i<100;i++){
已同步(新整数(计数)){
++计数;
系统输出打印项次(计数);
}
}
}
}
输出 四, 6. 8. 9 10 11 12 5. 14 15 3. 17 十八


一些想法?

是的,有一个竞争条件,因为您实际上在不同的对象上同步代码。 同步块表示一个关键部分。要进入关键区域,必须获得全局锁。可以将对象用作锁或整数。 我将这样实施:

class HiloContador extends Thread {

    static int count = 0;
    static Object lock = new Object();

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (lock) {
                ++count;
                System.out.println(count);
            }
        }
    }
}
类HiloContador扩展线程{
静态整数计数=0;
静态对象锁=新对象();
@凌驾
公开募捐{
对于(int i=0;i<100;i++){
已同步(锁定){
++计数;
系统输出打印项次(计数);
}
}
}
}

现在,println将按预期顺序运行。

是的,存在争用条件,因为您实际上同步了不同对象上的代码。 同步块表示一个关键部分。要进入关键区域,必须获得全局锁。可以将对象用作锁或整数。 我将这样实施:

class HiloContador extends Thread {

    static int count = 0;
    static Object lock = new Object();

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (lock) {
                ++count;
                System.out.println(count);
            }
        }
    }
}
类HiloContador扩展线程{
静态整数计数=0;
静态对象锁=新对象();
@凌驾
公开募捐{
对于(int i=0;i<100;i++){
已同步(锁定){
++计数;
系统输出打印项次(计数);
}
}
}
}
现在,println将按预期顺序运行。

Analysis 此代码中是否存在竞争条件


是,存在竞速条件:该行表示不正确的同步:

synchronized (new Integer(count)) {
原因如下。
让我们参考文档:

每个对象都有一个与之关联的内在锁。按照惯例,需要以独占和一致方式访问对象字段的线程必须在访问对象字段之前获取对象的固有锁,然后在处理完这些字段后释放固有锁。线程在获取锁和释放锁之间拥有内在锁。只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁。另一个线程在尝试获取锁时将阻塞

-

在本案中,第一句话至关重要。当前的实现使用一个新对象的内在锁来同步每个循环迭代。这是不正确的

解决方案概述 实现增量操作原子性的备选方案:

  • 使用内部锁(
    synchronized
    关键字)。见文章
  • 使用原子变量(
    java.util.concurrent.atomic
    包:
    AtomicBoolean
    AtomicInteger
    AtomicLong
    等类)。见文章
  • 使用lock对象(java.util.concurrent.locks包的类)。见文章
  • 极小解 让我们使用原子变量(解决方案#3),即
    AtomicInteger
    类:它内置了所需的功能

    另外,我们不要扩展
    线程
    类:而是提取适当的
    可运行
    接口实现

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class Program {
        public static void main(String[] args) throws InterruptedException {
            final CountingRunnable countingRunnable = new CountingRunnable();
            final List<Thread> threads = new ArrayList<>();
            for (int i = 0; i < 5; ++i) {
                final Thread thread = new Thread(countingRunnable);
                threads.add(thread);
                thread.start();
            }
    
            for (final Thread thread : threads) {
                thread.join();
            }
        }
    
        private static final class CountingRunnable implements Runnable {
            private final AtomicInteger count = new AtomicInteger(0);
    
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(count.incrementAndGet());
                }
            }
        }
    }
    
    import java.util.ArrayList;
    导入java.util.List;
    导入java.util.concurrent.AtomicInteger;
    公共课程{
    公共静态void main(字符串[]args)引发InterruptedException{
    final CountingRunnable CountingRunnable=新的CountingRunnable();
    最终列表线程=新的ArrayList();
    对于(int i=0;i<5;++i){
    最终螺纹=新螺纹(可计数运行);
    线程。添加(线程);
    thread.start();
    }
    用于(最终螺纹:螺纹){
    thread.join();
    }
    }
    私有静态最终类CountingRunnable实现Runnable{
    私有最终AtomicInteger计数=新的AtomicInteger(0);
    @凌驾
    公开募捐{
    对于(int i=0;i<100;i++){
    System.out.println(count.incrementAndGet());
    }
    }
    }
    }
    
    其他参考资料
  • 整个
  • 。要了解关系发生之前的情况
  • 分析 此代码中是否存在竞争条件


    是,存在竞速条件:该行表示不正确的同步:

    synchronized (new Integer(count)) {
    
    原因如下。
    让我们参考文档:

    每个对象都有一个与之关联的内在锁。按照惯例,需要以独占和一致方式访问对象字段的线程必须在访问对象字段之前获取对象的固有锁,然后在处理完这些字段后释放固有锁。线程在获取锁和释放锁之间拥有内在锁。只要一个线程拥有一个内在锁,其他线程就不能获得相同的锁。另一个线程在尝试获取锁时将阻塞

    -

    在本案中,第一句话至关重要。当前的实现使用一个新对象的内在锁来同步每个循环迭代。这是不正确的

    解决方案概述 实现增量操作原子性的备选方案:

  • 使用内部锁(
    synchronized
    关键字)。见文章
  • 使用原子变量