Synchronized学习笔记(1)-加锁方式

这两天在学习Synchronized锁的原理。之前只是知道怎么使用它,但是原理根本不了解,打算把学习的情况记录下来。

synchronized的作用就是给对象加锁,执行同步代码时只有获得了对象的锁才可以执行,如果对象的锁已经被其他线程获得了,那就需要等待。synchronized的加锁方式有很多种:给代码块加锁、给一般方法加锁、给静态方法加锁,但是不管怎么使用,synchronized锁住的只有两种,一种是实例对象,一种是类。锁住实例对象的时候,不同对象会拥有不同锁,而锁住整个类的时候,所有对象都用同一把锁。

举个例子:

class SynchronziedTest implements Runnable {
   public  void run() {
      synchronized(this) {
         for (int i = 0; i < 100; i++) {
            try {
               System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
            }
         }            
      }
   }
}

这明显是一个给实例对象加锁

SynchronziedTest syn= new SynchronziedTest();

Thread thread1 = new Thread(syn, "SyncThread1");

Thread thread2 = new Thread(syn, "SyncThread2");

thread1.strat();thread2.start();

这时Thread1和Thread2会顺序执行

可是把它改为

Thread thread1 = new Thread(new SynchronziedTest(), "SyncThread1");

Thread thread2 = new Thread(new SynchronziedTest(), "SyncThread2");

这时候再运行的话,thread1和thread2就会交叉运行

如果把synchronized加锁方式改为

 synchronized(SynchronziedTest.class)

那么这就变成了类锁,这样不管执行上面的哪种代码,都是顺序执行。因为都获取的是同一锁。

简单总结:

A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。 

B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。 

C(预告).如果线程没有得到它需要的锁,那么他就会被挂起,等到能获得锁的时候再去恢复。这个过程需要程序进入操作系统的内核态来完成,这样是比较浪费时间的。如果一个程序执行时间所需时间还不如挂起和恢复的时间长,那么效率会大大下降,所以还是会有自选锁,以及后面为了减少锁的获得和释放带来的性能消耗所引入的偏向锁以及轻量级锁,我会在后面学习,并且把自己学到的东西总结下来。


猜你喜欢

转载自blog.csdn.net/qq_29568299/article/details/79786082