java 同步鎖問題(synchronized)
阿新 • • 發佈:2018-10-31
Java中cpu分給每個執行緒的時間片是隨機的並且在java中好多都是多個執行緒共用一個資源,比如火車賣票,火車票是一定的,但賣火車票的視窗到處都有,每個視窗就相當於一個執行緒,這麼多的執行緒共用所有的火車票這個資源。如果在一個時間點上,兩個執行緒同時使用這個資源,那他們取出的火車票是一樣的(座位號一樣),這樣就會給乘客造成麻煩。比如下面程式:
[java] view plain copy print ?- package com.pakage.ThreadAndRunnable;
- public class Runnable_demo implements Runnable{
- private int ticket=10;
- public Runnable_demo(){
- }
- @Override
- public void run() {
- for(int i=0;i<20;i++){
- if
- //休眠1s秒中,為了使效果更明顯,否則可能出不了效果
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");
- }
- }
- }
- public static void main(String args[]){
- Runnable_demo demo=new Runnable_demo();
- //基於火車票建立三個視窗
- new Thread(demo,"a").start();
- new Thread(demo,"b").start();
- new Thread(demo,"c").start();
- }
- }
程式執行結果:
我們可以看到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 print ?- package com.pakage.ThreadAndRunnable;
- public class Runnable_demo implements Runnable{
- private int ticket=10;
- public Runnable_demo(){
- }
- @Override
- public void run() {
- for(int i=0;i<20;i++){
- if(this.ticket>0){
- //休眠1s秒中,為了使效果更明顯,否則可能出不了效果
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- this.sale();
- }
- }
- }
- public synchronized void sale(){
- if(this.ticket>0){
- System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");
- }
- }
- public static void main(String args[]){
- Runnable_demo demo=new Runnable_demo();
- //基於火車票建立三個視窗
- new Thread(demo,"a").start();
- new Thread(demo,"b").start();
- new Thread(demo,"c").start();
- }
- }
程式的輸出結果為:
2、使用同步塊修改上面的例子:
[java] view plain copy print ?- package com.pakage.ThreadAndRunnable;
- public class Runnable_demo implements Runnable{
- private int ticket=10;
- public Runnable_demo(){
- }
- @Override
- public void run() {
- for(int i=0;i<20;i++){
- <span style="color:#ff0000">synchronized</span>(this){
- if(this.ticket>0){
- //休眠1s秒中,為了使效果更明顯,否則可能出不了效果
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName()+"號視窗賣出:"+this.ticket--+"號票");
- }
- }
- }
- }
- public static void main(String args[]){
- Runnable_demo demo=new Runnable_demo();
- //基於火車票建立三個視窗
- new Thread(demo,"a").start();
- new Thread(demo,"b").start();
- new Thread(demo,"c").start();
- }
- }
程式的輸出結果:
摘自:http://blog.csdn.net/lianqiangjava/article/details/12652201/ 侵刪。