• JAVA多线程(3)——如何加锁


    1、加锁不正确导致数据不一致:m1执行过程中,m2(未加synchronized)可以执行,因为m2不用获得锁就可以执行

     1 public class TT implements Runnable {
     2     int b = 100;
     3     
     4     public synchronized void m1() throws Exception {
     5         b = 1000;
     6         System.out.println("in m1() before sleep,b="+b);
     7         Thread.sleep(5000);
     8         System.out.println("in m1() after sleep,b="+b);
     9     }
    10     
    11     public void m2() {
    12     //public synchronized void m2() throws Exception {
    13         b = 199;
    14         System.out.println("in m2(),b="+b);
    15     }
    16     
    17     public void run() {
    18         try {
    19             m1();
    20         } catch (Exception e) {
    21             e.printStackTrace();
    22         }
    23     }
    24     
    25     public static void main(String[] args) throws Exception {
    26         TT tt = new TT();
    27         System.out.println("in main() just after new TT(),b=" + tt.b);
    28         Thread t = new Thread(tt);
    29         t.start();
    30         
    31         Thread.sleep(1000);  //为了让m1能够执行b=1000的赋值
    32         tt.m2();           // 主线程执行m2
    33         
    34         System.out.println("in main() last,b=" + tt.b);
    35     }
    36 }

    结果:

    D:聚划算技术部编程练习TestThreadSync>java TT
    in main() just after new TT(),b=100
    in m1() before sleep,b=1000
    in m2(),b=199
    in main() last,b=199
    in m1() after sleep,b=199  //main线程先于t线程结束吗?

    说明:锁定当前对象 只是针对synchronized 这段话,另外的线程完全有可能访问没有锁定的方法(即不带synchronized 的方法)

    问题:要保证对资源b的正确访问,需要考虑所有访问b的所有方法,是否需要加同步:加了同步效率可能变低、不加同步可能会出现数据不一致

    问题:main线程先于t线程结束吗?

    解答:会,main方法即使执行完最后的语句,JVM也不会结束该程序,要等到主线程中的所有其它线程都结束之后,才结束该JAVA应用程序

    2、解决上述访问资源b,数据不一致的问题:把所有访问b的方法加锁,m1执行过程,m2一定执行不了,执行m2时必须要得到当前对象的锁才能执行

     1 public class TT implements Runnable {
     2     int b = 100;
     3     
     4     public synchronized void m1() throws Exception {
     5         b = 1000;
     6         System.out.println("in m1() before sleep,b="+b);
     7         Thread.sleep(5000);
     8         System.out.println("in m1() after sleep,b="+b);
     9     }
    10     
    11     public synchronized void m2() {
    12     //public synchronized void m2() throws Exception {
    13         b = 199;
    14         System.out.println("in m2(),b="+b);
    15     }
    16     
    17     public void run() {
    18         try {
    19             m1();
    20         } catch (Exception e) {
    21             e.printStackTrace();
    22         }
    23     }
    24     
    25     public static void main(String[] args) throws Exception {
    26         TT tt = new TT();
    27         System.out.println("in main() just after new TT(),b=" + tt.b);
    28         Thread t = new Thread(tt);
    29         t.start();
    30         
    31         Thread.sleep(1000);  //为了让m1能够执行b=1000的赋值
    32         tt.m2();
    33         
    34         System.out.println("in main() last,b=" + tt.b);
    35     }
    36 }

    结果:

    D:聚划算技术部编程练习TestThreadSync>java TT
    in main() just after new TT(),b=100
    in m1() before sleep,b=1000
    in m1() after sleep,b=1000  //m1执行完了才会执行m2
    in m2(),b=199
    in main() last,b=199

    举例:

    如何加锁:——设定同步对象时较麻烦
    数据库中的某一个记录,可以改、也可以读,一般情况下哪个方法应该加锁?
    (1)读:允许多个线程同时读
    (2)改:要加synchronized ,不允许两个线程同时改
  • 相关阅读:
    初识计算机
    前端html css
    mysql高级
    mysql多表查询
    mysql数据库查询
    mysql表关系
    mysql数据类型
    mysql数据库介绍
    异步回调 协程
    GIL-全局解释器锁
  • 原文地址:https://www.cnblogs.com/wxdlut/p/3361993.html
Copyright © 2020-2023  润新知