精华内容
下载资源
问答
  • 对象锁和类锁

    2020-03-17 12:16:05
    对象锁和类锁 https://blog.csdn.net/q5706503/article/details/84996537?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-ta...

                                           对象锁和类锁

    对象锁

    Synchronized修饰非静态方法,是对调用该方法的对象加锁,俗称“对象锁”。

    这里的对象加锁并非是说执行该加锁方法的时候整个对象的所有成员都不允许其他线程访问了,

    而是说该对象内所有的加锁的非静态方法共用这一把锁, 一个加锁非静态方法执行, 另一个加锁非静态方法不能执行,要等持有锁的线程释放锁, 不同对象之间的方法不互相作用

    这里举第一个例子:

    两个线程执行同一个对象不同加锁非静态方法, 预期互斥执行,即同一对象的两个加锁的非静态方法共用该锁:

    package test;
     
    public class Test1 {
    	synchronized void  fun1() throws InterruptedException {
    		System.out.println("加锁的方法1开始执行");
    		Thread.sleep(2000);
    		System.out.println("加锁的方法1执行结束");
    	}
    	synchronized void  fun2() throws InterruptedException {
    		System.out.println("加锁的方法2开始执行");
    		Thread.sleep(2000);
    		System.out.println("加锁的方法2执行结束");
    	}
    }

    两个线程分别执行同一个对象的两个方法 

    package test;
     
    public class TestSyntro {
     
    	public static void main(String[] args) {
    		Test1 obj1=new Test1();
    		
    		new Thread() {
    			@Override
    			public void run() {
    				try {
    					obj1.fun1();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}; 
    		}.start();
    		
    		new Thread() {
    			@Override
    			public void run() {
    				try {
    					obj1.fun2();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}; 
    		}.start();
    	}
    }

    结果:

     说明两个方法是互斥执行的, 共用一把锁

    那么我们把第二个方法的锁去掉,看看同一个对象加锁的方法运行时不加锁的方法是否可以执行:

    (由于篇幅,以后例子都由上例微改得到, 不再重复贴代码, 也是因为本来就是给新手看, 太长反而让人晕,注意描述,加锁与否, 几个对象,静态,非静态)

     说明同一对象加锁方法不影响为加锁的方法

    我们用两个线程执行两个对象的加锁方法, 预期不互斥, 证明不同对象不共用非静态锁:

     

     

    只是改了第二个线程的执行方法的对象:

    package test;
     
    public class TestSyntro {
     
    	public static void main(String[] args) {
    		Test1 obj1=new Test1();
    		Test1 obj2=new Test1();
    		new Thread() {
    			@Override
    			public void run() {
    				try {
    					obj1.fun1();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}; 
    		}.start();
    		
    		new Thread() {
    			@Override
    			public void run() {
    				try {
    					obj2.fun2();
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}; 
    		}.start();
    	}
    }

     不互斥说明不同对象的非静态锁不共用

     

    Synchronized修饰静态方法,是对该类对象加锁,俗称“类锁”。

    同样, 这里的对象加锁并非是说执行该加锁方法的时候整个类的所有(静态)成员都不允许其他线程访问了,

    而是说该类内所有的加锁的静态方法共用这一把锁, 一个加锁静态方法执行, 同类另一个加锁静态方法不能执行,要等持有锁的线程释放锁

    还是上面的程序, 两个方法全是静态, 都加锁,:

    两个线程分别执行该类两个对象的静态加锁方法, 预期互斥执行, 证明与对象无关

    互斥执行, 说明该锁由类中静态方法共用

    我们把一个方法写成静态, 一个不静态, 都加锁, 由两个类调用同一个对象的两个方法, 预期不互斥, 证明静态与非静态方法不共用锁:

    不互斥,说明静态与非静态方法不共用锁

     

    synchronized方法与synchronized代码块的区别
    synchronized methods() {} 与 synchronized (this) {} 之间并没有什么区别。

    只是前者便于阅读理解,而后者可以更精确的控制冲突限制访问区域(粒度更小),锁的范围没有变,锁住的时间变短了因而性能更好。

    synchronized(this)与synchronized(class)的区别

    首先this 和class 分别是两把不同的锁,不会存在class被获取,this就要等的现象。
    synchronized加在一个类的普通方法上,那么相当于synchronized(this)
    如果synchronized加载一个类的静态方法上,那么相当于synchronized(Class对象)。
     

    总结:

    • 静态方法的锁属于类, 一个类中所有加锁的静态方法共用该锁
    • 非静态方法的锁属于对象,  一个对象中所有加锁的非静态方法共用, 和静态方法的锁不同而互不相干
    • 加锁的方法的执行不会影响同一个类/对象中未加锁的方法的执行(因为其他方法没有锁呀)

    有参考下文:

    https://www.jianshu.com/p/8327c5c15cb8

    在这里插入图片描述

     

    展开全文
  • java对象锁和类锁

    2020-07-23 14:20:04
    最近发现有很多初学java多线程基础的同学会问到对象锁和类锁会相互影响吗,本篇文章首先介绍下对象锁和类锁,然后从基础原理角度说明下具体关系。 对象锁(实例锁) 我们知道,类声明后,我们可以 new 出来很多...

    最近发现有很多初学java 多线程基础的同学会问到对象锁和类锁会相互影响吗,本篇文章首先介绍下对象锁和类锁,然后从基础原理角度说明下具体关系。

     

    对象锁(实例锁)

    我们知道,类声明后,可以 new 出来很多的实例对象,每个实例在 JVM 中都有自己的引用地址和堆内存空间,这些实例都是独立的个体。很显然,在实例上加的锁和其他的实例就没有关系,互不影响了。所以使用对象锁的情况,只有使用同一实例的线程才会受锁的影响,多个实例调用同一方法也不会受影响。

    通常我们使用实例锁的方式有下面三种:

    1、 锁住实体里的非静态变量

    2、 锁住 this 对象

    3、 直接锁非静态方法

     

    类锁

    对象锁是用来控制实例方法之间的同步,类锁是用来控制静态方法(或静态变量互斥体)之间的同步。类锁是加载类上的,而类信息是存在 JVM 方法区的,并且整个 JVM 只有一份,方法区又是所有线程共享的,所以类锁是所有线程共享的。

    使用类锁的方式有如下方式:

    1、锁住类中的静态变量

    因为静态变量和类信息一样也是存在方法区的并且整个 JVM 只有一份,所以加在静态变量上可以达到类锁的目的。

    2、直接在静态方法上加 synchronized

    因为静态方法同样也是存在方法区的并且整个 JVM 只有一份,所以加在静态方法上可以达到类锁的目的。

    3、锁住 xxx.class

    对当前类的 .class 属性加锁,可以实现类锁。

     

    对象锁与类锁是否相互影响

    我们现在来梳理下,类锁和对象锁不是同一个东西,类锁是指类的Class对象的锁,对象锁是类的实例的锁,所以他们之间不会相互影响。例如线程A访问MyClass的类锁,线程B访问MyClass的实例mc的对象锁,他们之间不会受到相互影响

    展开全文
  • 跳转仙女棒一、概念二、对象锁和类锁三、根据使用对象和使用方法分类根据修饰对象分类根据获取的锁分类四、总结五、测试代码测试类锁测试对象锁 一、概念 synchronized 是 Java 中的关键字,是利用锁的机制来实现...

    一、概念

    synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的。

    锁机制有如下两种特性:

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

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

    二、对象锁和类锁

    • 对象锁 在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java
      对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。
    • 类锁
      在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。
      synchronized 的用法可以从两个维度上面分类:

    三、根据使用对象和使用方法分类

    根据修饰对象分类

    synchronized 可以修饰方法和代码块

    修饰代码块

    • synchronized(this|object) {}
    • synchronized(类.class) {}

    修饰方法

    • 修饰非静态方法
    • 修饰静态方法

    根据获取的锁分类

    获取对象锁

    • synchronized(this|object) {}
    • 修饰非静态方法

    获取类锁

    • synchronized(类.class) {}
    • 修饰静态方法,非静态方法

    四、总结

    • 对于静态方法采用类锁;
    • 对于非静态方法,同一个实例的线程访问会被拦截,非同一实例可以同时访问。 即此时是默认对象锁(this)。
    • 只要采用类锁,就会拦截所有线程,只能让一个线程访问。
    • 对于对象锁(this),如果是同一个实例,就会按顺序访问,但是如果是不同实例,就可以同时访问。
    • 如果对象锁跟访问的对象没有关系,那么就会都同时访问。

    五、测试代码

    测试类锁

    public class testMain {
        private  static  int count;
    
        public static void main(String[] args) {
    
            for (int i = 0; i < 2; i++) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(10);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //每个线程让count自增100次
                        for (int i = 0; i < 100; i++) {
                            synchronized (this.getClass()){
                                count++;
                            }
                        }
                    }
                }).start();
            }
    
            try{
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(count);
        }
    }
    
    

    此处用this.getclass()为类锁,显示结果200
    使用this为对象锁,显示结果小于等于200随机数

    测试对象锁

    import org.jetbrains.annotations.NotNull;
    
    public class testMain2 {
        private  static  int count;
    
        public static void main(String[] args) {
            Runnable target = getTarget();
    
            for (int i = 0; i < 2; i++) {
                new Thread(target).start();
            }
    
            try{
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println(count);
        }
    
        @NotNull
        private static Runnable getTarget() {
            return new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(10);
                    } catch ( Exception e ) {
                        e.printStackTrace();
                    }
                    //每个线程让count自增100次
                    for (int i = 0; i < 100; i++) {
                        synchronized (this) {
                            count++;
                        }
                    }
                }
            };
        }
    }
    
    

    此处无论是否使用this.getClass 还是 this 均返回200,对象锁生效

    文章参考博客园 huansky synchronized(this) 与synchronized(class) 之间的区别

    展开全文
  • 透彻理解 Java synchronized 对象锁和类锁的区别

    万次阅读 多人点赞 2017-02-17 14:34:05
    synchronized 加到 static 方法...对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。 在Task2 中定义三个方法 doLongTimeTaskA和doLongTimeTaskB是类锁,而doLongTimeTaskC是对象锁。pub

    synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。这两者的区别我用代码来演示下:

    1. 对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。

    在Task2 中定义三个方法 doLongTimeTaskA和doLongTimeTaskB是类锁,而doLongTimeTaskC是对象锁。

    public class Task2 {
    
        public synchronized static void doLongTimeTaskA() {
            System.out.println("name = " + Thread.currentThread().getName() + ", begain");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("name = " + Thread.currentThread().getName() + ", end");
        }
    
        public synchronized static void doLongTimeTaskB() {
            System.out.println("name = " + Thread.currentThread().getName() + ", begain");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("name = " + Thread.currentThread().getName() + ", end");
        }
    
        public synchronized void doLongTimeTaskC() {
    
            System.out.println("name = " + Thread.currentThread().getName() + ", begain");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("name = " + Thread.currentThread().getName() + ", end");
    
        }
    

    三个线程的代码如下:

    class ThreadA extends Thread{
        
        private Task2 mTask2;
        
        public ThreadA(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            mTask2.doLongTimeTaskA();
        }
    }
    
    class ThreadB extends Thread{
        
        private Task2 mTask2;
        
        public ThreadB(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            mTask2.doLongTimeTaskB();
        }
    }
    
    class ThreadC extends Thread{
        
        private Task2 mTask2;
        
        public ThreadC(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            mTask2.doLongTimeTaskC();
        }
    }
    

    main函数中执行代码如下:

            Task2 mTask2 = new Task2();
            ThreadA ta = new ThreadA(mTask2);
            ThreadB tb = new ThreadB(mTask2);
            ThreadC tc = new ThreadC(mTask2);
            
            ta.setName("A");
            tb.setName("B");
            tc.setName("C");
            
            ta.start();
            tb.start();
            tc.start();
    

    执行的结果如下:

    name = A, begain, time = 1487311199783
    name = C, begain, time = 1487311199783
    name = C, end, time = 1487311200784
    name = A, end, time = 1487311200784
    name = B, begain, time = 1487311200784
    name = B, end, time = 1487311201784
    

    可以看出由于 doLongTimeTaskA和doLongTimeTaskB都是类锁,即同一个锁,所以 A和B是按顺序执行,即同步的。而C是对象锁,和A/B不是同一种锁,所以C和A、B是 异步执行的。(A、B、C代指上面的3中方法)。

    我们知道对象锁要想保持同步执行,那么锁住的必须是同一个对象。下面就修改下上面的来证明:

    Task2.java不变,修改ThreadA 和 ThreadB 如下:

    class ThreadA extends Thread{
        
        private Task2 mTask2;
        
        public ThreadA(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            mTask2.doLongTimeTaskC();
        }
    }
    
    class ThreadB extends Thread{
        
        private Task2 mTask2;
        
        public ThreadB(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            mTask2.doLongTimeTaskC();
        }
    }
    

    main方法如下:

     Task2 mTaska = new Task2();
     Task2 mTaskb = new Task2();
     ThreadA ta = new ThreadA(mTaska );
     ThreadB tb = new ThreadB(mTaskb );
            
            
     ta.setName("A");
     tb.setName("B");
            
     ta.start();
     tb.start();
          
    

    结果如下:

    name = A, begain, time = 1487311905775
    name = B, begain, time = 1487311905775
    name = B, end, time = 1487311906775
    name = A, end, time = 1487311906775
    

    从结果看来,对象锁锁的对象不一样,分别是mTaska , mTaskb,所以线程A和线程B调用 doLongTimeTaskC 是异步执行的。

    但是,类锁可以对类的所有对象的实例起作用。只需修改ThradA
    和 ThreadB,main 方法不做改变,修改如下:

    class ThreadA extends Thread{
        
        private Task2 mTask2;
        
        public ThreadA(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
            //mTask2.doLongTimeTaskC();
            mTask2.doLongTimeTaskA();
        }
    }
    
    class ThreadB extends Thread{
        
        private Task2 mTask2;
        
        public ThreadB(Task2 tk){
            mTask2 = tk;
        }
        
        public void run() {
           //mTask2.doLongTimeTaskC();
            mTask2.doLongTimeTaskA();
        }
    }
    

    结果如下:

    name = A, begain, time = 1487312239674
    name = A, end, time = 1487312240674
    name = B, begain, time = 1487312240674
    name = B, end, time = 1487312241674
    

    可以看出 在线程A执行完doLongTimeTaskA方法后,线程B才会获得该类锁接着去执行doLongTimeTaskA。也就是说,类锁对所有的该类对象都能起作用。

    总结:

    1. 如果多线程同时访问同一类的 类锁(synchronized 修饰的静态方法)以及对象锁(synchronized 修饰的非静态方法)这两个方法执行是异步的,原因:类锁和对象锁是2中不同的锁。
    2. 类锁对该类的所有对象都能起作用,而对象锁不能。

    以后文章会同步到个人公众号,欢迎关注交流
    在这里插入图片描述

    展开全文
  • 对象锁和类锁的区别

    千次阅读 2020-04-12 16:47:25
    对象锁和类锁的区别synchronized 关键字对象锁1、锁住 this 对象2、 锁住实体里的非静态变量3、直接锁非静态方法对象锁代码测试类锁1、锁住 xxx.class2、锁住类中的静态变量3、直接在静态方法上加 synchronized类锁...
  • 对象锁和类锁的区别 使用对象锁的情况,只有使用同一实例的线程才会受锁的影响,多个实例调用相同方法也不会受到影响。 类锁是所有线程共享的锁,所以相同时刻,只能有一个线程使用加了锁的方法或方法体,不管是不是...
  • 具体知识学习与 ... ... 下面是自己的理解+代码: 一.前置知识: ... java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对...
  • 对象锁和类锁问题实验 今天遇到了一个问题,就是当获取到类锁时还能获取到该类的对象锁吗? 实验一 都是获取类锁,显然会实现同步 public class Solution { /*实验结果 获得类锁,睡觉zzz 起床... 获得对象锁 ...
  • 说一下对象锁和类锁?

    2020-06-14 14:22:36
    1.Java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,实际区别大 2.对象锁是用于对象实例方法,或者一个对象实例上的 3.类锁是用于类的静态方法或者一个类的class对象上的. 4.类的对象实例可以有很多个,...
  • 对象锁和类锁的区别 对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的...
  • 对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。 所以我们用代码来演示下 首先准备工作,先创建一个Task类 新建三个方法其中两个 是static修饰静态的。 /** * @Title: dmdemo ...
  • synchronized 对象锁和类锁的区别

    千次阅读 2018-05-31 20:36:40
    synchronized 对象锁和类锁的区别 synchronized 描述 一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限, 在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁); 如果这个时候...
  • Java学习-锁-synchronized之对象锁和类锁 0x01 摘要 synchronized是java中最常用的一种锁机制,本篇文章主要介绍他的两种用途:类锁和对象锁。 0x02 对象锁 synchronized作为对象锁时,用在非静态方法或非静态...
  • 看名字就已经很明显了,类锁就是所在类上的锁,实例就是锁在类实例上的锁。 实例锁: 类声明后,我们可以 new 出来很多的实例对象。这时候,每个实例在 JVM 中都有自己的引用地址堆内存空间,这时候,我们就认为...
  • 透彻理解java中Synchronized对象锁和类锁的区别 java内置锁 ​ java内置锁:每个java对象都可以用做一个实现同步的锁,这些锁称为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法的...
  • 对象锁和类锁是否会互相影响

    千次阅读 2018-02-24 16:30:09
     对象锁和类锁是否会互相影响?· 对象锁:Java的所有对象都含有1个互斥锁,这个锁由JVM自动获取和释放。线程进入synchronized方法的时候获取该对象的锁,当然如果已经有线程获取了这个对象的锁,那么当前线程会...
  • synchronized 加到 static 方法后面是给class 加锁,即类锁; 而synchronized 加到非静态方法前面是给对象上锁。...对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的...
  • 你能谈谈Java中 synchronized 对象锁和类锁的区别 synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。 这两者的区别我用代码来演示下 对象锁和类锁是不同...
  • Java的锁分为对象锁和类锁。  1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码...
  • 原文地址:http://www.cnblogs.com/cangqiongbingchen/p/5806757.html Java的锁分为对象锁和类锁。 1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的...
  • 本文主要是从上一个博主上面摘抄下来,再以synchronized关键字用法作为例子来去解释Java中的对象锁和类锁。 一、synchronized关键字 synchronized关键字有如下两种用法: 1、 在需要同步的方法的方法签名中加入...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,471
精华内容 2,188
关键字:

对象锁和类锁