java同步锁正解!!!!!(有详细妮子)

简介: java中cpu分给每个线程的时间片是随机的并且在java中好多都是多个线程共用一个资源,比如火车卖票,火车票是一定的,但卖火车票的窗口到处都有,每个窗口就相当于一个线程,这么多的线程共用所有的火车票这个资源。

java中cpu分给每个线程的时间片是随机的并且在java中好多都是多个线程共用一个资源,比如火车卖票,火车票是一定的,但卖火车票的窗口到处都有,每个窗口就相当于一个线程,这么多的线程共用所有的火车票这个资源。如果在一个时间点上,两个线程同时使用这个资源,那他们取出的火车票是一样的(座位号一样),这样就会给乘客造成麻烦。比如下面程序:

[java]  view plain  copy
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.                 if(this.ticket>0){  
  11.                     //休眠1s秒中,为了使效果更明显,否则可能出不了效果  
  12.                     try {  
  13.                         Thread.sleep(1000);  
  14.                     } catch (Exception e) {  
  15.                         e.printStackTrace();  
  16.                     }  
  17.                     System.out.println(Thread.currentThread().getName()+"号窗口卖出:"+this.ticket--+"号票");  
  18.                 }  
  19.               
  20.         }  
  21.     }  
  22.       
  23.      public static void main(String args[]){  
  24.          Runnable_demo demo=new Runnable_demo();  
  25.          //基于火车票创建三个窗口  
  26.          new Thread(demo,"a").start();  
  27.          new Thread(demo,"b").start();  
  28.          new Thread(demo,"c").start();  
  29.      }  
  30.       
  31. }  

程序运行结果:

54097b6e87097463ace2671210e15ed4e3c3eae3

我们可以看到c号窗口和和b号窗口都卖出了10号票,并且a号和b号窗口分别卖出了0号和-1号票。造成这种情况的原因是1、c线程和b线程在ticket=10的时候,c线程取出10号票以后,ticket还没来的及减1,b线程就取出了ticket此时ticket还等于10;2、在ticket=1时,c线程取出了1号票,ticket还没来的及减1,a、b线程就先后进入了if判断语句,这时ticket减1了,那么当a、b线程取票的时候就取到了0号和-1号票。

出现了上述情况怎样改变呢,我们可以这样做:当一个线程要使用火车票这个资源时,我们就交给它一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程。这样就不会出现上述情况。 实现这个锁的功能就需要用到synchronized这个关键字。

synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。

1、使用同步方法将上面的例子该为:

[java]  view plain  copy
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.                 if(this.ticket>0){  
  11.                     //休眠1s秒中,为了使效果更明显,否则可能出不了效果  
  12.                     try {  
  13.                         Thread.sleep(1000);  
  14.                     } catch (Exception e) {  
  15.                         e.printStackTrace();  
  16.                     }  
  17.                     this.sale();  
  18.                 }  
  19.               
  20.         }  
  21.     }  
  22.       
  23.     public synchronized void sale(){  
  24.         if(this.ticket>0){  
  25.             System.out.println(Thread.currentThread().getName()+"号窗口卖出:"+this.ticket--+"号票");  
  26.         }  
  27.     }  
  28.       
  29.      public static void main(String args[]){  
  30.          Runnable_demo demo=new Runnable_demo();  
  31.          //基于火车票创建三个窗口  
  32.          new Thread(demo,"a").start();  
  33.          new Thread(demo,"b").start();  
  34.          new Thread(demo,"c").start();  
  35.      }  
  36.       
  37. }  

程序的输出结果为:

2、使用同步块修改上面的例子:

[java]  view plain  copy
  1. package com.pakage.ThreadAndRunnable;  
  2.   
  3. public class Runnable_demo implements Runnable{  
  4.     private int ticket=10;  
  5.     public Runnable_demo(){       
  6.     }  
  7.     @Override  
  8.     public void run() {  
  9.         for(int i=0;i<20;i++){  
  10.             <span style="color:#ff0000;">synchronized</span>(this){  
  11.                 if(this.ticket>0){  
  12.                     //休眠1s秒中,为了使效果更明显,否则可能出不了效果  
  13.                     try {  
  14.                         Thread.sleep(1000);  
  15.                     } catch (Exception e) {  
  16.                         e.printStackTrace();  
  17.                     }  
  18.                     System.out.println(Thread.currentThread().getName()+"号窗口卖出:"+this.ticket--+"号票");  
  19.                 }  
  20.             }  
  21.               
  22.         }  
  23.     }  
  24.       
  25.      public static void main(String args[]){  
  26.          Runnable_demo demo=new Runnable_demo();  
  27.          //基于火车票创建三个窗口  
  28.          new Thread(demo,"a").start();  
  29.          new Thread(demo,"b").start();  
  30.          new Thread(demo,"c").start();  
  31.      }  
  32.       
  33. }  

程序的输出结果:

目录
相关文章
|
2月前
|
Java API
JAVA同步锁CountDownLatch
JAVA同步锁CountDownLatch
|
2月前
|
Java 调度
JAVA同步锁Semaphore
JAVA同步锁Semaphore
|
3月前
|
Java
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
Java多线程同步锁、Lock锁和等待唤醒机制及代码演示
|
7月前
|
Java 编译器 C++
Java同步锁Synchronized底层源码和原理剖析
Java同步锁Synchronized底层源码和原理剖析
74 0
|
安全 Java
Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的。
110 0
|
Java
JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
利用实例介绍JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
119 0
JAVA同步锁 synchronized(this)、synchronized(class)与synchronized(Object)的区别
|
Java API
java多线程 -- 同步鎖
为了解决多线程安全问题在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile 。Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。
747 0
|
3天前
|
安全 Java 调度
Java线程:深入理解与实战应用
Java线程:深入理解与实战应用
20 0