java-zh 2023-06-07 08:54 采纳率: 77.8%
浏览 21
已结题

synchronized

了解一下,一个线程中是否可以调用多个synchronized方法(包含方法,静态方法,代码块)


```java
public class SyncTest {
    //获取CPU个数
    private static int cpuCount = Runtime.getRuntime().availableProcessors();
    private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(cpuCount, cpuCount * 2, 20,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>(20000));

    static {
        System.out.println("我的cpu颗数: " + cpuCount);
    }

    //成员变量,可被多个线程 共享
    private static long a = 0L;
    private static long b = 0L;
    private static long c = 0L;

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(10000);
        SyncTest lockobj = new SyncTest();
        for (int i = 0; i < 10000; i++) {
            threadPool.execute(() -> {
                lockobj.sync(countDownLatch);
                sync2(countDownLatch);
                lockobj.sync3(countDownLatch);
            });
        }
        // 等待所有的线程执行完再打印
        countDownLatch.await();
        System.out.println("a=" + a);
        System.out.println("b=" + b);
        System.out.println("c=" + c);
    }

    /**
     * 修饰生源方法,其使用的锁对应时当前类所在的实例对象(或者说当前方法的调用对象),也就是this
     *
     * @param countDownLatch
     */
    private synchronized void sync(CountDownLatch countDownLatch) {
        try {
            a++;
        } finally {
            countDownLatch.countDown();
        }
    }

    /**
     * 修饰静态方法,使用的锁对象是当前类
     *
     * @param countDownLatch
     */
    private synchronized static void sync2(CountDownLatch countDownLatch) {
        try {
            b++;
        }  finally {
            countDownLatch.countDown();
        }
    }

    private void sync3(CountDownLatch countDownLatch) {
        try {
            synchronized (countDownLatch) {
                c++;
            }
        }  finally {
            countDownLatch.countDown();
        }
    }

}

结果:
a=3339
b=3334
c=3332

比如上面这段代码,如果三个代码在同一个线程,甚至两个代码在同一个线程,得出的结果集都不正确。
  • 写回答

2条回答 默认 最新

  • WuWuII 2023-06-07 15:15
    关注

    你的结果不对,是因为你的线程还没结束,你就输出结果了,不要用countDownLatch.await();
    用threadPool.getActiveCount()判断它是不是执行完了,只要不等于0,就是还没结束
    这一段改一下

        public static void main(String[] args) throws InterruptedException {
            CountDownLatch countDownLatch = new CountDownLatch(10000);
            SyncTest lockobj = new SyncTest();
            for (int i = 0; i < 10000; i++) {
                threadPool.execute(() -> {
                    lockobj.sync(countDownLatch);
                    sync2(countDownLatch);
                    lockobj.sync3(countDownLatch);
                });
            }
    
            while (threadPool.getActiveCount()!=0){
                Thread.sleep(100);
            }
    
            threadPool.shutdown();
    
            System.out.println("a=" + a);
            System.out.println("b=" + b);
            System.out.println("c=" + c);
        }
    
    

    img

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 6月16日
  • 已采纳回答 6月8日
  • 创建了问题 6月7日

悬赏问题

  • ¥15 winFrom界面无法打开
  • ¥15 crossover21 ARM64版本安装软件问题
  • ¥15 mymetaobjecthandler没有进入
  • ¥15 mmo能不能做客户端怪物
  • ¥15 osm下载到arcgis出错
  • ¥15 Dell g15 每次打开eiq portal后3分钟内自动退出
  • ¥200 使用python编写程序,采用socket方式获取网页实时刷新的数据,能定时print()出来就行。
  • ¥15 matlab如何根据图片中的公式绘制e和v的曲线图
  • ¥15 我想用Python(Django)+Vue搭建一个用户登录界面,但是在运行npm run serve时报错了如何解决?
  • ¥15 QQ邮箱过期怎么恢复?