【问题标题】:Java concurrency issue - Locks and Synchronize methodJava 并发问题 - Locks 和 Synchronize 方法
【发布时间】:2015-05-07 19:11:18
【问题描述】:

我正在研究可重入锁并尝试将其与同步相关联。然而,这两个课程都给了我意想不到的结果。我期望 arrayList 有 0 到 9。但是这两个程序都不会出现这个值。请建议。 带锁:

package Threads;

import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Locking {

    Lock lock = new ReentrantLock(true);
    ArrayList<Integer> al = new ArrayList<Integer>();
    static int count = 0;

    public void producer() {
        lock.lock();
        count++;
        al.add(count);
        System.out.println(al);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        // System.out.println("I came out of this block:"+Thread.currentThread().getName());
    }

    public void consumer() {
    }

    public static void main(String[] args) {
        // ExecutorService ex= Executors.newCachedThreadPool();
        ExecutorService ex = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            ex.submit(new Runnable() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    new Locking().producer();
                }

            });
        }
        ex.shutdown();
    }
}

使用同步:

package Threads;

import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LockwithSynchronize {

    ArrayList<Integer> al = new ArrayList<Integer>();
    static int count = 0;

    public synchronized void producer() {
        count++;
        al.add(count);
        System.out.println(al);
        try {
            Thread.sleep(5000);
            // System.out.println("I came out of this block:"+Thread.currentThread().getName());
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // ExecutorService ex= Executors.newCachedThreadPool();
        ExecutorService ex = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            ex.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    new LockwithSynchronize().producer();
                }
            });
        }
        ex.shutdown();
    }

}

【问题讨论】:

  • 你得到了什么输出?

标签: java multithreading java.util.concurrent


【解决方案1】:

这有很多问题。

首先,您希望它包含 0..9,但您在 al.add(count) 之前调用 count++,这意味着您实际上应该期待 1..10。

由于您每次都使用新的LockWithSynchronizeLocking,实际上没有任何共享锁——每个实例都有自己的锁,它不会与任何其他锁冲突,这意味着您的@987654325 @ 变量完全不受保护。而且您可能会定期收到损坏的ArrayList,因为add 在没有同步的情况下在多个线程上被调用,或者ConcurrentModificationException 或类似情况。

试试这个:

public static void main(String [] args){

    ExecutorService ex= Executors.newFixedThreadPool(10);

    final Locking producer = new Locking();

    for (int i=0; i<10;i++)
    {
        ex.submit(new Runnable(){

            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                producer.producer();
            }

        });
    }

    ex.shutdown();
}

请注意,我们不是每次都使用一个新的Locking,而是重用同一个实例,而您现在所期望的会发生:您非常快速地生成了十个线程,每个线程在尝试调用@987654331 之前等待两秒钟@。一个线程获得锁,而其他九个线程阻塞。获得锁的线程在退出之前等待锁五秒钟,此时下一个线程获得锁,等待五秒钟,然后退出,等等。所以这将需要将近一分钟的时间来运行。

类似的修改也修复了另一个。

【讨论】:

    【解决方案2】:

    您的同步不保护静态变量 - synchonize 仅在这样使用时锁定当前this 对象的监视器。任何produce() 调用都不会等待您发布的代码中的任何其他调用。锁定共享的东西 - 例如 LockWithProducer.class。

    【讨论】:

    • 另外,您到底期望什么输出?您真的想要为每个 LockWithSynchronize 提供一个列表吗?还是您想将所有线程输出到一个列表?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多