• 四、java多线程核心技术——synchronized同步方法与synchronized同步快


    一、synchronized同步方法

    论:“线程安全”与“非线程安全”是多线程的经典问题。synchronized()方法就是解决非线程安全的。

    1、方法内的变量为线程安全

    public void addI(String username) {
            try {
                int num = 0;     \方法内的变量为线程安全
                if (username.equals("a")) {
                    num = 100;
                    System.out.println("a set over!");
                    Thread.sleep(2000);
                } else {
                    num = 200;
                    System.out.println("b set over!");
                }
                System.out.println(username + " num=" + num);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    2、实例变量非线程安全

    public class HasSelfPrivateNum {
        private int num = 0;    \实例变量非线程安全
        public void addI(String username) {
            try {
                if (username.equals("a")) {
                    num = 100;
                    System.out.println("a set over!");
                    Thread.sleep(2000);
                } else {
                    num = 200;
                    System.out.println("b set over!");
                }
                System.out.println(username + " num=" + num);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }

    解决方法: 方法前加synchronized关键字。

    public class HasSelfPrivateNum {
    
        private int num = 0;
    
        synchronized public void addI(String username) {
           ..............
        }
    
    }

    3、多个对象多个锁

    HasSelfPrivateNum.java

    public class HasSelfPrivateNum {
    
        private int num = 0;
    
        synchronized public void addI(String username) {
            try {
                if (username.equals("a")) {
                    num = 100;
                    System.out.println("a set over!");
                    Thread.sleep(2000);
                } else {
                    num = 200;
                    System.out.println("b set over!");
                }
                System.out.println(username + " num=" + num);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }

    ThreadA

        
        public class ThreadA extends Thread {
        
            private HasSelfPrivateNum numRef;
        
            public ThreadA(HasSelfPrivateNum numRef) {
                super();
                this.numRef = numRef;
            }
        
            @Override
            public void run() {
                super.run();
                numRef.addI("a");
            }
        
        }
    ThreadB
    public class ThreadB extends Thread {
    
        private HasSelfPrivateNum numRef;
    
        public ThreadB(HasSelfPrivateNum numRef) {
            super();
            this.numRef = numRef;
        }
    
        @Override
        public void run() {
            super.run();
            numRef.addI("b");
        }
    
    }

    RUN

    public class Run {
    
        public static void main(String[] args) {
    
            HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
            HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
    
            ThreadA athread = new ThreadA(numRef1);
            athread.start();
    
            ThreadB bthread = new ThreadB(numRef2);
            bthread.start();
    
        }
    
    }

    结果:创建了2个业务实例,产生2个锁,所以运行结果是异步的。同步为synchronized  异步:asynchronized

    4、synchronized 锁重入

                       当一个线程得到一个对象锁时,再次请求该对象锁时是可以再次得到该对象的锁的。继承关系也可重入锁。

                       当一个线程执行发生异常时,其持有的锁会自动释放。

                       同步不具有继承性。的在子类方法中添加synchronized的关键字。

    public class HasSelfPrivateNum {
        synchronized public void service1() {
            System.out.println("service1");
            service2();
        }
    
        synchronized public void service2() {
            System.out.println("service2");
            service3();
        }
    
        synchronized public void service3() {
            System.out.println("service3");
        }
    }
    HasSelfPrivateNum.java
    public class mYThread extends Thread {
        @Override
        public void run() {
            HasSelfPrivateNum hspn=new HasSelfPrivateNum();
            hspn.service1();    
        }
       public static void main(String[] args) {
           mYThread mYThread=new mYThread();
           mYThread.start();
     }
    }
    mYThread.java

     二、synchronized同步快

        synchronized同步方法持有锁后,如果长时间不释放,那另一个线程就必须长时间等待。。这种情况下synchronized同步快来解决

    使用方法如图:

                    1、synchronized同步快之间具有同步性,当线程访问object的一个  synchronized(this)同步代码块时,其他线程对同一个object对象中所有其他的

    synchronized(this)同步代码块的访问会被阻塞。

                    2、synchronized(this)同步代码块是锁定当前对象的。

    1、synchronized同步快解决同步方法效率低得弊端

    public class Task {
    
        private String getData1;
        private String getData2;
    
        public synchronized void doLongTimeTask() {
            try {
                System.out.println("begin task");
                Thread.sleep(3000);
                getData1 = "长时间处理任务后从远程返回的值1 threadName="
                        + Thread.currentThread().getName();
                getData2 = "长时间处理任务后从远程返回的值2 threadName="
                        + Thread.currentThread().getName();
                System.out.println(getData1);
                System.out.println(getData2);
                System.out.println("end task");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    Task
    public class MyThread1 extends Thread {
    
        private Task task;
    
        public MyThread1(Task task) {
            super();
            this.task = task;
        }
    
        @Override
        public void run() {
            super.run();
            CommonUtils.beginTime1 = System.currentTimeMillis();
            task.doLongTimeTask();
            CommonUtils.endTime1 = System.currentTimeMillis();
        }
    
    }
    MyThread1
    public class MyThread2 extends Thread {
    
        private Task task;
    
        public MyThread2(Task task) {
            super();
            this.task = task;
        }
    
        @Override
        public void run() {
            super.run();
            CommonUtils.beginTime2 = System.currentTimeMillis();
            task.doLongTimeTask();
            CommonUtils.endTime2 = System.currentTimeMillis();
        }
    
    }
    MyThread2
    public class CommonUtils {
    
        public static long beginTime1;
        public static long endTime1;
    
        public static long beginTime2;
        public static long endTime2;
    }
    CommonUtils
    public class Run {
    
        public static void main(String[] args) {
            Task task = new Task();
    
            MyThread1 thread1 = new MyThread1(task);
            thread1.start();
    
            MyThread2 thread2 = new MyThread2(task);
            thread2.start();
    
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            long beginTime = CommonUtils.beginTime1;
            if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
                beginTime = CommonUtils.beginTime2;
            }
    
            long endTime = CommonUtils.endTime1;
            if (CommonUtils.endTime2 > CommonUtils.endTime1) {
                endTime = CommonUtils.endTime2;
            }
    
            System.out.println("耗时:" + ((endTime - beginTime) / 1000));
        }
    }
    Run

    修改Task

    public class Task {
    
        private String getData1;
        private String getData2;
    
        public void doLongTimeTask() {
            try {
                System.out.println("begin task");
                Thread.sleep(3000);
    
                String privateGetData1 = "长时间处理任务后从远程返回的值1 threadName="
                        + Thread.currentThread().getName();
                String privateGetData2 = "长时间处理任务后从远程返回的值2 threadName="
                        + Thread.currentThread().getName();
    
                synchronized (this) {
                    getData1 = privateGetData1;
                    getData2 = privateGetData2;
                }
                
                System.out.println(getData1);
                System.out.println(getData2);
                System.out.println("end task");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    View Code

  • 相关阅读:
    多线程关键字
    Atomic原子类
    FFmpeg滤镜代码级分析
    YUV420数据和字符信息如何利用滤镜方法进行编码?
    FFmpeg音视频编解码实践总结
    Android高手应该精通哪些内容
    CentOs 设置静态IP 方法
    花了5天时间,终于解决了一个bug,心情非常愉快,憋了这么久,不吐不快
    H264视频通过RTMP直播
    程序移植到VS2010,编译成功但是无法启动lib文件
  • 原文地址:https://www.cnblogs.com/aGboke/p/6523365.html
Copyright © 2020-2023  润新知