下面是自己的理解+代码:
一.前置知识:
但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的
二.代码理解
- synchronized(对象锁):两种;
synchronized(this){
//互斥代码
}
或:
private Object lock = new Object();
public void test1(){
synchronized(lock){
//互斥代码
}
}
这里的this,指的是调用它的实例对象,即锁就是这个这里对象 ; 而lock锁则是任意对象锁(所有需要这个对象的锁的方法都不能同时执行),有些许的不同(所有线程线程能共用该锁)。
- 代码:
Ticket t1=new Ticket(); Ticket t2=new Ticket(); Ticket t3=new Ticket();
t1.start(); t2.start(); t3.start();
//测试三个线程
class Ticket extends Thread{
private int num=100;
//Object obj = new Object();
public void run() {
while(true) {
//synchronized (obj)
synchronized (this) {
if(num>0)System.out.println(Thread.currentThread().getName()+".."+num--);
try {
Thread.sleep(100);
}catch (Exception e) {}
}
System.out.println(Thread.currentThread().getName()+":释放");
}
}
}
此时线程1.2.0.交替执行,但注意下一次线程1.2.0像执行必须对应锁释放,换句话说这里三个线程对象对应了三个锁,只锁自己,不能锁别人,cpu可以切换其他线程执行,只要没被锁。 而代码注释的第二种结果是:
与上面同理,也是只能锁自己。是把当前这个对象的成员变量(object)当做锁,其实三个线程对象有三个不同的object对象,因为这个变量不共享。
- tips:这样加锁的好处 (这是最常用的高并发场景下要锁住某个方法所用的操作)
private Object lock = new Object();
public void test1(){
synchronized(lock){
//互斥代码
}
}
private static Object lock = new Object();
但如果任意对象锁改为静态的,则可以实现互斥了,所有线程共享这个锁(共享这个变量)。
- synchronized(类锁)
- 对于类锁来说其实和对象锁一样只是为了区别静态方法和普通方法,对于多个线程,都是一把锁,和第5点的情况一样
synchronized(A.class){
//互斥代码
}
tips:object.getClass()和A.class实际意义不同,并且对于前者来说,出现多态时,可能会有问题
- 每个线程执行都得等内阁唯一的一把锁释放。
三:一点解释:
Thread.sleep():强制线程休眠未来*ms时间内不进入CPU进行竞争,进入阻塞状态,给其他线程机会执行,但是,他不会释放锁;且 *毫秒过去之后,这时候也许另外一个线程正在使用CPU,那么这时候操作系统是不会重新分配CPU的, 直到那个线程挂起或结束;况且,即使这个时候恰巧轮到操作系统进行CPU 分配,那么当前线程也不一定就是总优先级最高的那个,CPU还是可能被其他线程抢占去。也不一定会论到调度他。
线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。