zoukankan      html  css  js  c++  java
  • synchronized 基本用法

    常见三种使用方式

    1)普通同步方法,锁是当前实例;
    2)静态同步方法,锁是当前类的Class实例,Class数据存在永久代中,是该类的一个全局锁;
    3)对于同步代码块,锁是synchronized括号里配置的对象。

    方式一   普通方法通过synchronized修饰

       1)不采用synchronized     当创建两个线程对象  线程t1  t2中采用同一个实例化类对象  调用method方法  会交异步执行  互补影响

    package cn.ac.bcc.sync;
    /**
     * 普通同步方法通过synchronized修饰
     * @author Administrator
     *
     */
    public class PtMethod {
        
        /**
         * 1)不采用synchronized修饰
         * @param s
         */
        public  void method(String s){
            if(s.equals("a")){
                System.out.println(Thread.currentThread().getName()+": a");
                
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+": b");
            }
        }
        
        public static void main(String[] args) {
            //创建当前类对象实例
            final PtMethod ptMethod = new PtMethod();
            
            //创建线程
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod.method("a");
                }
            });
            
            Thread t2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod.method("b");
                }
                
            });
            
            t1.start();
            t2.start();
        }
    
    }
    View Code

     运行结果:

    Thread-1: b
    Thread-0: a

     2)采用synchronized   当创建两个线程对象  线程t1 t2 中采用同一个实例化对象  调用synchronized修饰的method方法  method方法中线程睡眠一秒钟  当线程t1优先抢占到method方法的执行权时由于method方法被synchronized修饰  method方法被实例化对象ptMethod对象锁锁住   当t2线程同样是ptMethod实例化对象调用当前method方法 由于两个线程t1 t2 都采用的是同一个实例化对象ptMethod 对象锁 只有t1运行完成后  t2中线程中的ptMethod对象才能调用method方法。由于method中获取当前调用线程睡眠  t2要等t1中调用的method睡眠唤醒之后执行完方法才能执行。

    public class PtMethod {
        
        /**
         * 1)采用synchronized修饰
         * @param s
         */
        public synchronized  void method(String s){
            if(s.equals("a")){
                System.out.println(Thread.currentThread().getName()+": a");
                
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+": b");
            }
        }
        
        public static void main(String[] args) {
            //创建当前类对象实例
            final PtMethod ptMethod = new PtMethod();
            
            //创建线程
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod.method("a");
                }
            });
            
            Thread t2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod.method("b");
                }
                
            });
            
            t1.start();
            t2.start();
        }
    
    }
    View Code

     3)采用synchronized修饰   创建两个线程对象  创建当前类实例对象 ptMethod1 ptMethod2  t1线程运行ptMetod1    t2线程运行ptMethod2 对象分别调用mehod方法  运行结果如下 ,由于两个线程分别采用的是两个不同的实例对象  当两个实例对象调用method方法时  synchronized判断当前锁对象并不相同  所以里两个对象向都分别调用了method方法,而不需要等待

    public class PtMethod {
        
        /**
         * 1)采用synchronized修饰
         * @param s
         */
        public synchronized  void method(String s){
            if(s.equals("a")){
                System.out.println(Thread.currentThread().getName()+": a");
                
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+": b");
            }
        }
        
        public static void main(String[] args) {
            //创建当前类对象实例
            final PtMethod ptMethod1 = new PtMethod();
            final PtMethod ptMethod2 = new PtMethod();
            
            //创建线程
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod1.method("a");
                }
            });
            
            Thread t2 = new Thread(new Runnable(){
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    ptMethod2.method("b");
                }
                
            });
            
            t1.start();
            t2.start();
        }
    
    }
    View Code

     运行结果:

    Thread-0: a

    Thread-1: b

    二、synchronized修饰静态方法
    采用synchronized  修饰的静态方法  两个线程通过不同的  类实例对象调用  这个方法  如何加锁  这是可以将该方法修改为static 方法  并synchronized修饰

    public class SyncDemo {
    
        /**
         * 类方法  synchronized修饰  解决多个线程调用当前类不同实例采用同步锁方法
         * @param s
         */
        public static  synchronized void method(String s){
            
            if(s.equals("a")){
                System.out.println(Thread.currentThread().getName()+": a");
                
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }else{
                System.out.println(Thread.currentThread().getName()+": b");
            }
        }
        
        public static void main(String[] args) {
            
            final SyncDemo syncDemo1 = new SyncDemo();
            final SyncDemo syncDemo2 = new SyncDemo();
            
            Thread t1 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo1.method("a");
                }
            });
            
            Thread t2 = new Thread(new Runnable(){
    
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo2.method("b");
                }});
            t1.start();
            t2.start();
        }
    }
    View Code

     三、同步代码块

      1)当两个并发线程同时访问一个对象的同步代码块synchronized(this),在某一时刻只有一条线程才能访问该同步代码块

    public class SyncDemo1 implements Runnable {
        
        
        public static void main(String[] args) {
        
            SyncDemo1 syncDemo1 = new SyncDemo1();
            new Thread(syncDemo1,"a").start();;
            new Thread(syncDemo1,"b").start();;
        }
    
        @Override
        public void run() {
            // TODO Auto-generated method stub
            System.out.println(Thread.currentThread().getName()+"执行开始run方法");
            synchronized (this) {
                System.out.println(Thread.currentThread().getName());
            }
        }
    
    }
    View Code

    运行结果:  当b抢到执行权只有b线程执行完成a线程才能继续执行

    b执行开始run方法
    b
    a执行开始run方法
    a

    2)当一个线程访问object对象中的synchronized(this)同步代码块时,另一个线程可以访问object对象的非同步代码块

    package cn.ac.bcc.sync;
    
    public class SyncDemo2 {
    
        public void method1(){
            synchronized (this) {
                System.out.println(Thread.currentThread().getName()+"线程同步代码块");
            }
        }
        
        public void method2(){
            System.out.println(Thread.currentThread().getName()+"当两个线程访问同一个object 中的方法   一个线程访问线程同步方法  另一个可以方位object对象的非线程同步方法");
        }
        
        public static void main(String[] args) {
            
            final SyncDemo2 syncDemo2 = new SyncDemo2();
            
            //创建两个线程对象
            Thread t1 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo2.method1();
                }
            },"t1");
            
            Thread t2 = new Thread(new Runnable(){
    
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo2.method2();
                }
                
            },"t2");
            
            t1.start();
            t2.start();
            
            
        }
    }
    View Code

    3)当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

    package cn.ac.bcc.sync;
    
    public class SyncDemo2 {
    
        public void method1(){
            synchronized (this) {
                System.out.println(Thread.currentThread().getName()+"线程同步代码块");
                try {
                    System.out.println(Thread.currentThread().getName()+"睡一会");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
        public void method2(){
            
            synchronized (this) {
                System.out.println(Thread.currentThread().getName()+"访问线程同步代码块");
            }
        }
        
        public static void main(String[] args) {
            
            final SyncDemo2 syncDemo2 = new SyncDemo2();
            
            //创建两个线程对象
            Thread t1 = new Thread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo2.method1();
                }
            },"t1");
            
            Thread t2 = new Thread(new Runnable(){
    
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    syncDemo2.method2();
                }
                
            },"t2");
            
            t1.start();
            t2.start();
            
            
        }
    }
    View Code

    运行结果:

    t1线程同步代码块
    t1睡一会

    10秒后t2才能访问当前对象其他同步代码块修饰的方法

    t1线程同步代码块
    t1睡一会
    t2访问线程同步代码块

  • 相关阅读:
    JMeter 关联
    JMeter MD5加密
    JMeter 时间函数
    JMeter 常用设置
    JMeter 服务器资源监控
    js制作列表滚动(有滚动条)
    js监听事件
    获取窗口大小 并自适应大小变化
    js 标签云
    js 显示数字不断增加
  • 原文地址:https://www.cnblogs.com/lwdmaib/p/9264255.html
Copyright © 2011-2022 走看看