• 线流中的锁


    线流中的锁

       线程同步本质: (数据同步)
           当多个线程(服务,任务),操作同一个数据的时候,保证数据一致.本质就是数据同步,是一种数据安全机制。
           这种机制,操作上更多是从数据上来保护的。
       异步编程模型:
           线程是完全独立的,谁的运行也不会受到别的线程的影响。
       同步编程模型:
           线程间不是独立的,相互间有影响的.某些线程必须单独完成任务以后,才能够让别的线程执行。
        同步的原因:
               一.  同步是指数据的同步,为了数据安全,必须要等某个线程对数据操作完成以后,在引入别的线程进行操作。
                   同步机制,某种程度是多线程编程变成了单线程。
               二.  同步的环境
                   1 必须多线程。
                   2 多个线程有同时操作同一个数据的可能性。
                   3 主要就是涉及数据更改的操作。
         线程同步是数据的概念
           方法:锁定,锁定是一个逻辑上的概念,是为了保证同步的手段。
           方法锁:按照封装性,根本不可能在是直接就能对数据进行操作,只能通过方法进行操作。
           对象锁:堆内存,只要一加锁,谁也进不来。
       只要加了 synchronized 成员方法,是多个线程不可以用加了synchronized的方法同时访问这个对象
       同一个方法互斥,不同的方法也互斥。

    实例:

     1 public class Thread_11_Synchronization{
     2     public static void main(String[] args){
     3         Account act = new Account("actNo_001",3000);
     4         Thread t1 = new Thread(new Processor(act));
     5         Thread t2 = new Thread(new Processor(act));
     6         t1.setName("t1---");
     7         t1.start();//2000;
     8         t2.setName("t2---");
     9         t2.start();//1000;
    10     }
    11 }
    12 //线程类
    13 class Processor implements Runnable{
    14     //一个账户,就开启一个线程
    15     Account act;
    16     //Processor
    17     Processor(Account act){
    18         this.act = act;
    19     }
    20     public void run(){
    21         act.withDraw(1000.0);//=================
    22         //我哪里睡一秒的目的,是为了这里输出争取时间
    23         System.out.println( "取款成功:1000.00, 余额是:" + Thread.currentThread().getName() + act.getBalance() );
    24     }
    25 }
    26 //实体类
    27 class Account{
    28     private String actNo;
    29     private double balance;
    30     public Account(){}
    31     public Account(String actNo, double balance){
    32         this.actNo = actNo;
    33         this.balance = balance;
    34     }
    35     public double getBalance(){
    36         return balance;
    37     }
    38     public void setActNo(String actNo){
    39         this.actNo = actNo;
    40     }
    41     public String getActNo(){
    42         return actNo;
    43     }
    44     public synchronized void setBalance(String actNo, double balance){
    45         if (this.actNo == actNo) {
    46             this.balance = balance;
    47         }
    48     }
    49     //实际的业务操作
    50     //synchronized:是让方法有能力锁定某个对象
    51     public synchronized void withDraw(double money){
    52         //synchronized(this);
    53         double after = balance - money;
    54         /**
    55          *  开始我们就看到,取钱两次,钱少了一次,所以有问题;
    56          *  这里我们引入一个锁的概念,和我们家用的锁区别不大:都是只允许某个人某些人操作,不让别人操作.这个是一个很重要的概念,就是为了数据的安全;数据库中也有;
    57          *  java中锁的关键字是synchronized,这个关键字并不是加锁,实际上每个对象,都有自己的锁,每个类,也有自己的锁,这个关键字只是把锁锁上的动作,直到程序运行完成再打开锁,允许别的操作继续
    58          *  可以用于限制某个代码段或者某个方法
    59          */
    60         try{
    61             Thread.sleep(1000);//为什么睡眠一秒
    62         }catch(Exception e){
    63             e.printStackTrace();
    64         }
    65         //更新账户,真正对余额产生影响的是这里
    66         //System.out.println( Thread.currentThread().getName() + "线程进行操作,这个时候,别的线程是操作不了的" );
    67         this.setBalance(actNo,after);
    68         //System.out.println( Thread.currentThread().getName() + "线程进行操作,这个时候,别的线程是操作不了的" );
    69     }
    70 }

    看一下结果:

    但是在工作的时候,最怕的是写一个死锁,看一下死锁是什么样子的:

     1 public class Thread_14_synchronized{
     2     public static void main(String[] args)throws Exception{
     3         Thread t1 = new Thread(new Processor(new MyClass()));
     4         Thread t2 = new Thread(new Processor(new MyClass()));//我new的时候,调用的是该类无参构造,但是由于我指定了构造方法,所以编译器不会再给我生成一个无参构造.
     5         t1.setName("t1");
     6         t2.setName("t2");
     7         t1.start();//调用线程中的run()
     8         //延迟主线程,保证t1先执行
     9         Thread.sleep(1000);
    10         t2.start();
    11     }
    12 }
    13 //线程类的作用:调用业务类实现业务逻辑
    14 class Processor implements Runnable{
    15     MyClass mc;
    16     //这个是个什么东西?构造方法,
    17     Processor(MyClass mc){
    18         this.mc = mc;
    19     }
    20     public void run(){
    21         if ("t1".equals(Thread.currentThread().getName())) {
    22            //mc.m1(); 
    23            MyClass.m1();
    24         }
    25         if ("t2".equals(Thread.currentThread().getName())) {
    26             //mc.m2();   
    27             MyClass.m2();
    28         }
    29     }
    30 }
    31 //业务类:就是业务逻辑
    32 class MyClass {//死锁
    33     public synchronized static void m1(){//加在静态方法上面的锁叫类锁,只有有这个类锁完全解除,也就是说没有任何静态方法执行的时候,才会交出锁,让下一个执行
    34         //目的,在执行该方法中,不会被别的线程打断
    35         try{
    36             //System.out.println( "" );
    37             Thread.sleep(5000);//这个5秒的作用就是保证m1()在执行的时候,就不会被执行的一个演示效果
    38         }catch(Exception e){
    39             e.printStackTrace();
    40         }
    41         System.out.println( "m1() 方法被执行了" );
    42     }
    43     public synchronized static void m2(){
    44         System.out.println( "m2() 方法被执行了" );
    45     }
    46 }

    这就是一个死锁,虽然不一定锁死,但是一旦锁死,就会让程序终止!

  • 相关阅读:
    广播机制(二)笔记
    ContentProvider初步笔记
    图解 Android 广播机制
    android 笔记 wifi应用
    仰望穹苍,且听风吟
    contentprovider的学习实例总结
    XML文件解析 笔记
    WIFI 网络操作笔记
    Handler队列
    property的使用【Delphi版】
  • 原文地址:https://www.cnblogs.com/atongmyuxiaowanzi/p/4823100.html
Copyright © 2020-2023  润新知