线程8锁

  • 思路: 线程 操作 共享资源

1)创建资源类,在资源类中定义线程操作方法,根据需要添加同步锁或同步代码块
2)创建线程对象,使用线程对象调用响应的同步方法

  • 对象锁和类锁的定义:
  • 对象锁:
    1)对象锁也叫方法锁,是针对一个对象实例的,它只在该对象的某个内存位置声明一个标识该对象是否拥有锁,所有它只会锁住当前的对象,而并不会对其他对象实例的锁产生任何影响,不同对象访问同一个被synchronized修饰的方法的时候不会阻塞
    2)synchronized修饰的非静态方法,即非静态同步方法
    3)synchronized(this),即非静态同步代码块
  • 类锁:
    1)synchronized static 修饰的静态方法,即静态同步方法
    2)synchronized(类名.class),即静态同步代码块
  • 位置:
  • 对象锁:堆内存中
  • 类锁:方法区中
  • 范围:
  • 对象锁:
    1)同一个线程对象如果有多个synchronized方法,同一时间只能访问一个synchronized方法
    2)锁的是this线程对象本身,不同线程对象之间的锁互不影响
  • 类锁:
    1)锁的是类名.class,这个对象是类加载对象的唯一,永远只能有一把锁
  • 执行顺序:判断多个线程对象TA、TB对应的调用方法MA、MB,是对象锁、类锁、没锁
  • MA、MB都是对象锁
    判断条件:TA、TB是否是同一个对象
    1)是,依调用顺序,必须等前一个方法释放锁之后,后一个方法才能执行
    2)不是,互不影响
  • MA、MB中一个是对象锁另一个是类锁
    判断条件:TA、TB是否是同一个对象
    1)是,互不影响
    2)不是,互不影响
  • MA、MB都是类锁
    判断条件:TA、TB是否是同一个对象
    1)是,依调用顺序,必须等前一个方法释放锁之后,后一个方法才能执行
    2)不是,依调用顺序,必须等前一个方法释放锁之后,后一个方法才能执行
  • MA、MB中一个是同步方法(对象锁或类锁)另一个是普通方法
    判断条件:TA、TB是否是同一个对象
    1)是,互不影响
    2)不是,互不影响
    3)普通的方法不受对象锁、类锁的约束,只跟调用顺序有关,即在调用普通方法之前,该线程对象在调用了一个synchronize的方法后且没有释放锁时,也不会影响调用该普通方法
  • 示例:
  • 1)两个普通同步方法,两个线程,打印?
   public static void main(String[] args){
       Number number = new Number();
       new Thread(new Runnable() {
           @Override
           public void run() {
               number.getOne();
           }
       }).start(); 
       new Thread(new Runnable() {
           @Override
           public void run() {
               number.getTwo();
           }
       }).start();
   }
}
class Number{
   public synchronized void getOne(){
       System.out.println("one");
   }
   public synchronized void getTwo(){
       System.out.println("two");
   }
}
  • 2)新增Thread.sleep()给getOne()方法,打印?
public synchronized void getOne(){
     try {
         Thread.sleep(3000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     System.out.println("one");
 }
  • 3)新增Thread.sleep()给getOne()方法,打印?
public class TestThread8Monitor {
 public static void main(String[] args){
     Number number = new Number();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number.getOne();
         }
     }).start();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number.getTwo();
         }
     }).start();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number.getThree();
         }
     }).start();
 }
}
class Number{
 public synchronized void getOne(){
     try {
         Thread.sleep(3000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     System.out.println("one");
 }
 public synchronized void getTwo(){
     System.out.println("two");
 }
 public void getThree(){
     System.out.println("three");
 }
}
  • 4)两个普通同步方法,两个Number对象,打印?
public class TestThread8Monitor {
 public static void main(String[] args){
     Number number = new Number();
     Number number1 = new Number();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number.getOne();
         }
     }).start();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number1.getTwo();
         }
     }).start();
 }
}
class Number{
 public synchronized void getOne(){
     try {
         Thread.sleep(3000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     System.out.println("one");
 }
 public synchronized void getTwo(){
     System.out.println("two");
 }
}
  • 5)将getOne()方法设置成static,一个对象,两个线程,打印?
public static synchronized void getOne(){
     try {
         Thread.sleep(3000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     System.out.println("one");
 }
  • 6)修改两个方法均为static方法,一个number对象,打印?
public static synchronized void getTwo(){
     System.out.println("two");
 }
  • 7)一个static同步方法,一个非static同步方法,两个对象,打印?
public class TestThread8Monitor {
 public static void main(String[] args){
     Number number = new Number();
     Number number1 = new Number();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number.getOne();
         }
     }).start();
     new Thread(new Runnable() {
         @Override
         public void run() {
             number1.getTwo();
         }
     }).start();
 }
} 
class Number{
 public static synchronized void getOne(){
     try {
         Thread.sleep(3000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
     System.out.println("one");
 }
 public  synchronized void getTwo(){
     System.out.println("two");
 }
 
}
  • 8)两个static同步方法,两个Number对象,打印?
public static synchronized void getTwo(){
     System.out.println("two");
 }
  • 结果:
> - 1)
one 
two
> - 2)
one 
two
> - 3) 
three
one
two
> - 4)
two
one
> - 5)
two
one
> - 6)
one
two
> - 7)
two
one
> - 8)
one
two

你可能感兴趣的:(Java锁)