这段java并发代码为啥经常不能正常运行?

//本来我是想比较一下Synchronized和Lock的性能的
public class SynchronizedVSLock {
    static final Lock lock = new ReentrantLock();
    static final int loopTime = 10;
    static final int numOfThread = 6;
    static final Random random = new Random();
    static final Semaphore runningThreadsNum = new Semaphore(numOfThread);
    //这个代码会产生不同的运行结果,但是我不知道原因
    public static void main(String[] args) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < numOfThread - 1; i++) {
            new Thread(new Test1()).start();
        }
        new Thread(new Test1()).join();
        runningThreadsNum.acquire(numOfThread);
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);
    }

    static class Test1 implements Runnable {
        @Override
        public void run() {
            try {
                runningThreadsNum.acquire();
            } catch (InterruptedException e) {
                throw new RuntimeException();
            }
            for (int i = 0; i < SynchronizedVSLock.loopTime; i++) {
                SynchronizedVSLock.lock.lock();
                System.out.println(SynchronizedVSLock.random.nextDouble());
                SynchronizedVSLock.lock.unlock();
            }
            runningThreadsNum.release();
        }
    }

    static class Test2 implements Runnable {
        @Override
        public void run() {
            try {
                runningThreadsNum.acquire();
            } catch (InterruptedException e) {
                throw new RuntimeException();
            }
            for (int i = 0; i < SynchronizedVSLock.loopTime; i++) {
                synchronized (SynchronizedVSLock.lock) {
                    System.out.println(SynchronizedVSLock.random.nextDouble());
                }
            }
            runningThreadsNum.release();
        }
    }
}

 

我看你代码你是想主线程通过调用其它线程的join()方法等其它线程执行完后再执行主线程,那你可以这样写:


        for (int i = 0; i < numOfThread; i++) {
            Thread thread = new Thread(new Test1());
            thread.start();
            thread.join();
        }

 

大致思路就是创建几个线程,并发地执行输出随机数的任务,分别采用lock锁和synchronized关键字两个同步机制。

最后输出程序的运行时间来作为指标。

用信号量来保证Main线程需要在所有子线程都结束后才能获取结束时的运行时间

但我发现Main线程经常在其他子线程运行之前就获得了所有信号量许可,然后输出一个很小的运行时间,就1、2毫秒,我不知道哪里出了问题,我听说过指令重排的概念,我听说过as-if-serial语义,我听说过HB原则,但我还是不知道哪里出了问题,sad.

你应该用CountDownLatch而不是信号量

谢谢提醒,CountDownLatch我第一次听说,应该能解决我本来的问题

但是我现在更想知道新问题出现的原因

又学到了,可是我还是不知道为什么

而且new Thread(new Test1()).join();这样写线程都没有启动的

哦我好像知道为什么了

是我对join方法理解有问题,谢谢你

for循环里面写join不行,会让整个线程串联运行

并行就写成两个for循环,一个start一个join

用Lock自己控制加锁与解锁时,解锁操作写在finally里,要注意一下