• java线程学习之synchronized关键字


    关键字synchronized的作用是实现线程间的同步。它的任务是对同步的代码加锁。一个代码块同时只能有同一个线程进行读和写操作,从而保证线程间是安全的。

    线程安全的概念是:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。反之就是线程不安全的。

    一、为什么要用synchronized?

         举个例子,老王有张储蓄卡,里面有一万块钱,老王通过无卡取现要取八千,操作过程中,会先查询储蓄金额,发现是一万,当输入八千的时候系统会让他支取。如果在老王的媳妇在这时拿着卡通过柜台要支取七千块钱,如果取钱的代码没有synchronized同步控制,他们同时进行查询的操作,发现金额是一万,两人输入金额同时进行取钱操作,就有可能都能取出需要的钱来,共计15000,这样的话,银行就会亏了,显示也是不安全的。

    如果上个例子理解不了,那么看下面例子:

     1 public class TestSynchorized implements Runnable {
     2   Timer timer = new Timer();
     3   public static void main(String[] args) {
     4     TestSync test = new TestSync();
     5     Thread t1 = new Thread(test);
     6     Thread t2 = new Thread(test);
     7     t1.setName("t1"); 
     8     t2.setName("t2");
     9     t1.start(); 
    10     t2.start();
    11   }
    12   public void run(){
    13     timer.add(Thread.currentThread().getName());
    14   }
    15 }
    16 
    17 class Timer{
    18   private static int num = 0;
    19   public  void add(String name){ 
    20         num ++;
    21         try {Thread.sleep(1);} 
    22         catch (InterruptedException e) {}
    23         System.out.println(name+", 你是第"+num+"个使用timer的线程");
    24       
    25   }
    26 }

    运行结果为:

    在上面19行如果加了synchronized 关键字后的结果

    为什么这样呢:

    先分析没加的时候,主线程创建了线程 t1 和线程 t2 , t2 先执行Timer类,这时执行完 num++,num的值为1此时线程 执行  Thread.sleep(1) 语句, t2 线程休眠1毫秒,此时 t1 线程执行Timer类,同样执行完 num++语句,num的值为2,此时线程 执行  Thread.sleep(1) 语句,t1 线程进行休眠 。 t2休眠结束,继续执行打印输出语句,随后  t1 也休眠结束,继续执行打印输出语句。

    加完synchronized后执行情况呢,同样 t1 先执行执行到  add(String name)  方法,发现有 synchronized ,此时就会独占此资源,即使是在休眠的时候也不允许 t2 执行 add(String name) 方法,只有当 t1 把add 方法执行完毕退出去后,才让 t2  执行 add(String name)  方法。

    可能会有疑问,为什么没加 synchronized 关键字前 是 t2 先执行,加了 synchronized 后是 t1 先执行?  其实java虚拟机jvm执行线程的时候的顺序跟书写代码的顺序无关,跟cpu执行线程的顺序有关,执行的时候,谁在前,谁就先执行。这个当然不是绝对的 ,它还受到优先级的影响。但优先级一样的时候,是这样的。

    二、synchronized用法 

        1、给指定的对象加锁,进入同步代码前要获得当前实例的锁。

        2、直接作用于实例方法,相当于对当前实例加锁,同步代码前要获得实例的锁。

        3、直接作用于静态方法,相当于对当前类加锁,同步代码前要获得当前类的锁。

    三、synchronized方法与synchronized代码块

        synchronized静态方法的锁的示例:

          

             synchronized代码块的示例:

               

    四、synchronized的作用

          1、synchronized可确保线程同步,线程安全。正如之上所言。

          2、synchronized能保证线程间的可见性。

                可见性:一个线程对共享变量值的修改,能够及时的被其他线程看到。

         synchronized可以完全替代volative的功能,只是在使用上没有volative使用方便。

          3、synchronized保证线程间的有序性。

                  因为synchronized限制每次只能允许一个线程可以访问代码块,因此无论怎么使用同步块内的代码如何被打乱顺序,只要保证串行语义一致,那么执行结果总是一样的。而其他访问线程,又必须在获得锁后方能进入代码块读取数据,因此,看到的最终结果并不取决于代码的执行过程,从而有序性自然得到了解决。

    生于忧患,死于安乐
  • 相关阅读:
    ajax理论
    模块
    node.js(1)
    ES6
    data对象
    数组
    对象
    webdriver对应的驱动版本
    TrineaAndroidCommon API Guide
    PV,UV,IP概念
  • 原文地址:https://www.cnblogs.com/songlove/p/10622945.html
Copyright © 2020-2023  润新知