锁就是对于操作资源的一种权限
对于一个资源加锁后,每次只能有一个线程对该资源进行操作,当该线程操作结束后,才会解锁。
 解锁之后,所有的线程获得竞争此资源的机会。
方法前加synchronized关键字
synchronized锁重入
synchronized同步代码块
synchronized关键字与synchronized代码块的区别
当两个线程访问同一个对象的synchronized代码块时,只有一个线程可以得到执行,另一个线程只能等待当前线程执行完才能执行。
下面对“一半同步,一半异步”进行代码验证
package ltl0002;  public class Task {      public void doTask(){         for (int i = 0; i < 100; i++) {             System.out.println("no synchronized ThreadName = " + Thread.currentThread().getName() + " i = " + (i+1));         }         synchronized (this){             for (int i = 0; i < 100; i++) {                 System.out.println("synchronized ThreadName = " + Thread.currentThread().getName() + " i = " + (i+1));             }         }              } } package ltl0002;  public class MyThread1 implements Runnable{      private Task task = new Task();      public MyThread1(Task task){         this.task = task;     }      @Override     public void run() {          task.doTask();     } } package ltl0002;  public class MyThread2 implements Runnable{      private Task task = new Task();      public MyThread2(Task task){         this.task = task;     }      @Override     public void run() {          task.doTask();     } } 文件Run.java代码如下:
package ltl0002;  public class Run {     public static void main(String[] args) {         Task task = new Task();         MyThread1 myThread1 = new MyThread1(task);         MyThread2 myThread2 = new MyThread2(task);         Thread tr1 = new Thread(myThread1);         Thread tr2 = new Thread(myThread2);         tr1.start();         tr2.start();     }  } 程序运行结果如图所示
进入synchronized代码块之后,排队运行,运行结果如图所示
在第一张图我们可以看到,线程0 和 1交叉输出,说明是异步进行,而在第二张图可以看出线程0运行完之后,线程1才运行,说明它们是同步运行,验证完毕。
package ltl0003; /**  * @author liTianLu  * @Date 2022/4/23 15:53  * @purpose 成员变量有int num,以及get set方法  */ public class Number {   private int num;   private boolean change = false;    public int getNum() {     return num;   }    public void setNum(int num) {     this.num = num;   }   public boolean isChangeing(){     return change;   }    public void setChange(boolean change) {     this.change = change;   } } 两个线程类的代码如下:
package ltl0003; /**  * @author liTianLu  * @Date 2022/4/23 15:36  * @purpose 更改num的值  */ public class MyThread01 implements Runnable{   static int num = 0;   Number number;   public MyThread01(Number num ){     this.number = num ;   }   @Override   public void run() {     synchronized (this){       number.setChange(true);       for (int i = 0; i < 10000; i++) {         number.setNum(num++);       }       number.setChange(false);     }   } } package ltl0003;  import static java.lang.Thread.sleep; /**  * @author liTianLu  * @Date 2022/4/23 15:35  * @purpose 读取num的值  */ public class MyThread02 implements Runnable{   Number number;    public MyThread02(Number num ){     this.number = num ;   }    @Override   public void run() {     for (int i = 0; i < 1000 ; i++) {       //如果number正在更改,就休眠1ms       while(number.isChangeing()){         try {           sleep(1);         } catch (InterruptedException e) {           e.printStackTrace();         }       }       System.out.println(Thread.currentThread().getName()+"的输出为: num = " + number.getNum());     }   }  } 主函数文件Run代码如下:
package ltl0003; /**  * @author liTianLu  * @Date 2022/4/23 15:15  * @purpose 解决锁问题 线程一对num进行修改,线程二三对num进行读取,此代码要实现:线程一与线程二三同步执行,而线程二三异步执行。  */ public class Run {   public static void main(String[] args) {     Number number = new Number();     number.setNum(0);     MyThread01 myThread01 = new MyThread01(number);     MyThread02 myThread02 = new MyThread02(number);     Thread tr1 = new Thread(myThread01);     Thread tr2 = new Thread(myThread02);     Thread tr3 = new Thread(myThread02);     tr1.start();     tr2.start();     tr3.start();   } } 实验结果如图所示

我们发现,线程2/3执行的时候,线程1已经执行完毕,且线程2、3异步进行。
ReentrantLock lock = new ReentrantLock ();  lock.lock();//加锁 lock.unlock();//解锁          //使用try catch finally 可以确保finally 中的代码执行,在finally中解锁 try{     while(true){         lock.lock ();         //操作代码     } }catch (Exception e) {     e.printStackTrace(); }finally {     lock.unlock (); }