synchronized的三种方式

第一种

package com.yang.lock;

public class Demo01 {
   public static void main(String[] args) {

       //这两个还是同一个类型
       TicketRunnable ticketRunnable = new TicketRunnable();//创建一个对象
       TicketRunnable ticketRunnable1 = new TicketRunnable();
       //Thread thread = new Thread(new TicketRunnable(), "第一个窗口");
       //Thread thread1 = new Thread(new TicketRunnable(), "第二个窗口");
       Thread thread = new Thread(ticketRunnable, "第一个窗口");
       Thread thread1 = new Thread(ticketRunnable, "第二个窗口");

       System.out.println(ticketRunnable.getClass()==ticketRunnable1.getClass());//true

       thread.start();
       thread1.start();
  }


}

class TicketRunnable implements Runnable {
   static int num = 1;

   @Override
   public void run() {
       while (num <= 100) {
           /*
           synchronized 修饰代码块 锁是Object类型,但是注意:需要保证多个线程使用的是同一把锁才能锁住。
              synchronized ("锁") {} 括号中的值:
                  1.固定值 :锁 指向一个地址
                  2.this称为对象锁,操作线程传递的对象必须是同一个。
                  //Thread thread = new Thread(new TicketRunnable(), "第一个窗口");
                  //Thread thread1 = new Thread(new TicketRunnable(), "第二个窗口");
                  //这是两个对象,所以不行。
                  3.Object.class 存放的是一个class类型,称为类锁。

            */
           /*synchronized (this) {
               if (num <= 100) {

                   System.out.println(Thread.currentThread().getName() + "个窗口卖了" + num + "张票");
                   num++;

               } else {
                   System.out.println("票已经卖完了");
               }*/
               /*synchronized ("lock") {
               if (num <= 100) {

                   System.out.println(Thread.currentThread().getName() + "个窗口卖了" + num + "张票");
                   num++;

               } else {
                   System.out.println("票已经卖完了");
               }*/
               synchronized (Object.class) {
               if (num <= 100) {

                   System.out.println(Thread.currentThread().getName() + "个窗口卖了" + num + "张票");
                   num++;

              } else {
                   System.out.println("票已经卖完了");
              }

          }
      }
  }
}

第二,三种

package com.yang.lock;
/*
  synchronized 修饰成员方法。
    1] synchronized 建议不和run()方法结合使用
    2] synchronized 锁的就是this。
    3]因为当前锁的是对象锁this,所以要保证是同一个对象
  synchronized 修饰静态成员方法。
     1] 当前锁 就是类锁 ,传递对象的字节码.class
     2] 同一个类创建出不同的对象,但他们对应的.getClass()是一样的

*/
public class Demo02 {
   public static void main(String[] args) {
       //对象锁 同一个对象
       /*TicketRunnable ticketRunnable = new TicketRunnable();//创建一个对象

       Thread thread = new Thread(ticketRunnable, "第一个窗口");
       Thread thread1 = new Thread(ticketRunnable, "第二个窗口");

       thread.start();
       thread1.start(); */
       //类锁 同一个类
       TicketRunnable ticketRunnable = new TicketRunnable();//创建一个对象
       TicketRunnable ticketRunnable1 = new TicketRunnable();

       Thread thread = new Thread(ticketRunnable, "第一个窗口");
       Thread thread1 = new Thread(ticketRunnable1, "第二个窗口");

       thread.start();
       thread1.start();

  }
}


class Ticket implements Runnable{
   static int num = 1;

   @Override
   public void run() {
       //demo1();
         demo2();
  }

   //修饰方法上,这被称为对象锁(this)
  /* public synchronized void demo1 (){

       if (num <= 100) {

           System.out.println(Thread.currentThread().getName() + "个窗口卖了" + num + "张票");
           num++;

       } else {
           System.out.println("票已经卖完了");
       }
   }*/
   //修饰静态方法上,这被称为类锁 .class
   public static synchronized void demo2 (){

       if (num <= 100) {

           System.out.println(Thread.currentThread().getName() + "个窗口卖了" + num + "张票");
           num++;

      } else {
           System.out.println("票已经卖完了");
      }
  }
}
 

synchronized 缺点

  1. 如果获得锁的线程由于要等待IO或者其它原因(如sleep())被阻塞了。但又没有释放锁,其它线程只能等待,此时会影响执行效率,甚至造成死锁。

  2. 只要获得了synchronized锁,不管是读操作,还是写操作,都要上锁,都会独占。如果希望多个读操作同时运行,一个写操作运行,是无法实现的。

  3.