zoukankan      html  css  js  c++  java
  • synchronized的使用

    概念:

    是利用锁的机制来实现同步的。

    锁机制有如下两种特性:

    互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。

    可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。

    为什么要使用synchronized:

    在并发编程中存在线程安全问题,主要原因有:

    1.存在共享数据

    2.多线程共同操作共享数据。

    synchronized的作用:

    关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见(可见性),即可以代替volatile。synchronized的用法

    1.普通同步方法(实例方法),锁是当前实例对象 ,进入同步代码前要获得当前实例的锁

     public class synchronizedTest implements Runnable {
        static synchronizedTest instance=new synchronizedTest();
        static int i=0;
        @Override
        public void run() {
            //省略其他耗时操作....
            //使用同步代码块对变量i进行同步操作,锁对象为instance
            synchronized(instance){
                for(int j=0;j<10000;j++){
                    i++;
                }
            }
        }
        public static void main(String[] args) throws InterruptedException {
            Thread t1=new Thread(instance);
            Thread t2=new Thread(instance);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println(i);
        }
    }
    

      

    2.静态同步方法,锁是当前类的class对象 ,进入同步代码前要获得当前类对象的锁

    (1)      同步非静态方法

     //修饰非静态方法
    
        //代码块1(对象)this指的是当前对象
        public  void accessResources1(){
            synchronized(this){
                try {
                    synchronized (this){
                        TimeUnit.MINUTES.sleep(2);
                    }
                    System.out.println(Thread.currentThread().getName()+" is runing");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        //代码块1(CLASS类)
        public  void accessResources4(){
            synchronized(SynchroDemo01.class){//ClassLoader  class  ——-》堆   Class   所有的对象
               //有Class对象的所有的对象都共同使用这一个锁
                try {
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println(Thread.currentThread().getName()+" is runing");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        public static void main(String[] args) {
            final SynchroDemo01 deno01=new SynchroDemo01();
            for (int i = 0; i < 5; i++) {
                new Thread(deno01::accessResources1).start();
            }
        }

    (2)      同步静态方法

    public class synchronizedTest implements Runnable {
        //共享资源
        static int i =0;
        /**
         * synchronized 修饰实例方法
         */
        public static synchronized void increase(){
            i++;
        }
        @Override
        public void run(){
            for (int j =0 ; j<10000;j++){
                increase();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(new synchronizedTest());
            Thread t2 = new Thread(new synchronizedTest());
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println(i);
        }

    根据获取的锁分类:

    synchronized从锁的是谁的维度一共有两种情况:

    1. 锁住类

    2. 锁住对象实例

    1)静态方法上的锁

    静态方法是属于“类”,不属于某个实例,是所有对象实例所共享的方法。也就是说如果在静态方法上加入synchronized,那么它获取的就是这个类的锁,锁住的就是这个类

    2)实例方法(普通方法)上的锁

    实例方法并不是类所独有的,每个对象实例独立拥有它,它并不被对象实例所共享。这也比较能推出,在实例方法上加入synchronized,那么它获取的就是这个累的锁,锁住的就是这个对象实例

    那锁住类还是锁住对象实例,

  • 相关阅读:
    (8) MySQL主从复制架构使用方法
    (7) MySQL数据库备份详解
    (6) MySQL慢查询日志的使用
    解决通过Nginx转发的服务请求头header中含有下划线的key,其值取不到的问题
    (5) 电商场景下的常见业务SQL处理
    (4) MySQL中EXPLAIN执行计划分析
    (3) MySQL分区表使用方法
    (2) 电商数据库表设计
    (1) Mysql高性能优化规范建议
    linux每日命令(39):lsof命令
  • 原文地址:https://www.cnblogs.com/grow001/p/12231515.html
Copyright © 2011-2022 走看看