zoukankan      html  css  js  c++  java
  • java 多线程: Thread 并发访问-代码块同步synchronized {};String作为被锁的对象

    方法同步的弊端

    方法同步的时候,如果一个方法需要线程安全控制的代码速度其实很快,但是有其他的业务逻辑代码耗时非常长(比如网络请求),这样所有的线程就在这一块就等待着了,这样造成了极大的资源浪费如果并发量很大,可能会造成系统崩溃。(并发的线程遇到synchronized同步的方法,变成串行....

    并发访问-代码块同步

    语法:

    synchronized (要锁住的对象) {
      并发执行且不耗时的业务计算代码;
    }
     
    代码示例: 方法同步比代码块同步耗时天壤地别
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * @ClassName ThreadSyncCode
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/22.
     */
    public class ThreadSyncCode {
        //子线程类外公共用来计算的变量
        private static int num = 0;
        //子线程对象
        private static class MyRannable implements Runnable {
            @Override
            public void run() {  //这里synchronized 导致耗时的IO操作也变为串行
                /**
                 * 模拟网络IO,磁盘IO耗时等待操作
                 */
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /**
                 * 避免多线程同时计算的代码块改为同步代码块。变为多线程到此串行执行;上面的IO耗时操作仍然并行
                 */
                synchronized (getClass()){
                    for (int i=0; i<1000; i++){
                        num++;
                    }
                }
                System.out.println(Thread.currentThread().getName() + " num result:" + num);
            }
        }
        public static void main(String[] args) {
            Set<Thread> threads = new HashSet<>();
            MyRannable myRannable = new MyRannable();
            for (int i=0; i<5; i++){
                threads.add(new Thread(myRannable,"线程"+i));
            }
            threads.forEach(thread -> thread.start());
    
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("main num result:" + num);
        }
    
    }

    方法同步IO耗时串行导致长达5S出结果。而代码块同步耗时1S多结束。

    String作为被锁的对象

    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * @ClassName ThreadMultiObjectSyncStringLock
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/4/22.
     */
    public class ThreadMultiObjectSyncStringLock {
        private static int num = 0;
        private static class MyThread extends Thread{
            private String lock;
    
            public MyThread(String name, String lock) {
                super(name);
                this.lock = lock;
            }
    
            @Override
            public void run() {
                synchronized (lock){
                    for (int i=0; i<1000; i++){
                        num++;
                    }
                    System.out.println(Thread.currentThread().getName() + "   num:" + num);
                }
            }
        }
        public static void main(String[] args) {
            //String锁对象
            String lock = "LOCK";
            //存放线程的集合
            Set<MyThread> myThreads = new HashSet<>();
            //向集合添加线程实例
            for (int i=0; i<5; i++){
                myThreads.add(new MyThread("T" +i, lock));
            }
            //启动所有线程
            myThreads.forEach(myThread -> myThread.start());
            //稍等时间主线程查看结果
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "num Result:" + num); //5000完全正确
        }
    }
    结果:最终打印出来的num的值就是5000,结果是正确的。但是我们发现我们在for循环创建我们的线程的时候,我们定义了5次lock,但是实际上这些lock是同一个对象(指向的是同一个内存地址),因为在JAVA中,字符串具有常量缓存的功能。所以会被锁起来。
  • 相关阅读:
    F# 语法概览
    Excel 帮助无法正常工作的解决方法
    autofac 组件的实例范围
    visual studio code 中隐藏从 ts 文件生成的 js 文件和 map 文件
    git vim 编辑器基本操作
    nhibernate 中 lazy="no-proxy" 时的问题
    什么是数据科学
    Elasticsearch 疑难解惑
    Hadoop MapReduce执行过程实例分析
    深入浅出JVM
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/14691099.html
Copyright © 2011-2022 走看看