zoukankan      html  css  js  c++  java
  • 架构师养成记--1线程基础

      为什么要拿线程开头呢?因为线程太重要了,先不说工作中有多重要,单是和money直接挂钩的开发工程师面试就必问题,要是面试没问相关问题的话,要么是应聘者太菜面试官懒得问了,要么是公司太菜,根本不关心多线程的问题。

    一、线程安全问题

      当多个线程访问某一个类的时候,这个类都能表现出正确的行为,那么这个类就是线程安全的。

      synchronized可以加在任意对象及方法上加锁,加锁的这段代码就成为互斥区或者临界区

      

      下面是关于线程安全的一个小示例,关键点就在synchronized这个词上

     1 import java.util.concurrent.atomic.AtomicInteger;
     2 
     3 /**
     4  * 线程安全概念:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。
     5  * synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区"
     6  * @author alienware
     7  *
     8  */
     9 public class MyThread extends Thread{
    10     
    11     private int count = 5 ;
    12     
    13     //synchronized加锁
    14     public synchronized void run(){
    15         count--;
    16         System.out.println(this.currentThread().getName() + " count = "+ count);
    17     }
    18     
    19     public static void main(String[] args) {
    20         /**
    21          * 分析:当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排对是按照CPU分配的先后顺序而定的),
    22          *         一个线程想要执行synchronized修饰的方法里的代码:
    23          *         1 尝试获得锁
    24          *         2 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,
    25          *            而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)
    26          */
    27         MyThread myThread = new MyThread();
    28         Thread t1 = new Thread(myThread,"t1");
    29         Thread t2 = new Thread(myThread,"t2");
    30         Thread t3 = new Thread(myThread,"t3");
    31         Thread t4 = new Thread(myThread,"t4");
    32         Thread t5 = new Thread(myThread,"t5");
    33         t1.start();
    34         t2.start();
    35         t3.start();
    36         t4.start();
    37         t5.start();
    38     }
    39 }

    二、多个线程多把锁

    多个线程,每个线程都能拿到自己指定的锁,拿到锁后执行synchronized方法体的内容.

    看看下面的示例代码,你觉得打印出来的结果会是什么样的呢?是不是觉得应该是这样的?

    (预想执行结果)

     1 /**
     2  * 关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,
     3  * 所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),
     4  * 
     5  * 在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。
     6  * @author alienware
     7  *
     8  */
     9 public class MultiThread {
    10 
    11     private int num = 0;
    12     
    13     /** static */
    14     public synchronized void printNum(String tag){
    15         try {
    16             
    17             if(tag.equals("a")){
    18                 num = 100;
    19                 System.out.println("tag a, set num over!");
    20                 Thread.sleep(1000);
    21             } else {
    22                 num = 200;
    23                 System.out.println("tag b, set num over!");
    24             }
    25             
    26             System.out.println("tag " + tag + ", num = " + num);
    27             
    28         } catch (InterruptedException e) {
    29             e.printStackTrace();
    30         }
    31     }
    32     
    33     //注意观察run方法输出顺序
    34     public static void main(String[] args) {
    35         
    36         //俩个不同的对象
    37         final MultiThread m1 = new MultiThread();
    38         final MultiThread m2 = new MultiThread();
    39         
    40         Thread t1 = new Thread(new Runnable() {
    41             @Override
    42             public void run() {
    43                 m1.printNum("a");
    44             }
    45         });
    46         
    47         Thread t2 = new Thread(new Runnable() {
    48             @Override 
    49             public void run() {
    50                 m2.printNum("b");
    51             }
    52         });        
    53         
    54         t1.start();
    55         t2.start();
    56         
    57     }
    58     
    59     
    60     
    61     
    62 }

     但实际上是这样的

     (实际结果)

    为什么会出现这样的结果呢?那是因为m1和m2是两个对象,t1和t2分别拿到的是m1和m2折两个对象的锁,所以这两个线程的执行互不相干。

    那我就像要得到之前预想的结果怎么办呢?那就使用类一级别的锁而不是对象锁,实现方法就是在除了加synchronized之外还需要static关键字。

     三、同步和异步

    直接上代码:

     1 /**
     2  * 对象锁的同步和异步问题
     3  * @author alienware
     4  *
     5  */
     6 public class MyObject {
     7 
     8     public synchronized void method1(){
     9         try {
    10             System.out.println(Thread.currentThread().getName());
    11             Thread.sleep(4000);
    12         } catch (InterruptedException e) {
    13             e.printStackTrace();
    14         }
    15     }
    16     
    17     /** synchronized */
    18     public void method2(){
    19             System.out.println(Thread.currentThread().getName());
    20     }
    21     
    22     public static void main(String[] args) {
    23         
    24         final MyObject mo = new MyObject();
    25         
    26         /**
    27          * 分析:
    28          * t1线程先持有object对象的Lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法
    29          * t1线程先持有object对象的Lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步
    30          */
    31         Thread t1 = new Thread(new Runnable() {
    32             @Override
    33             public void run() {
    34                 mo.method1();
    35             }
    36         },"t1");
    37         
    38         Thread t2 = new Thread(new Runnable() {
    39             @Override
    40             public void run() {
    41                 mo.method2();
    42             }
    43         },"t2");
    44         
    45         t1.start();
    46         t2.start();
    47         
    48     }
    49     
    50 }

    如果method2也加上了synchronized关键字,那么字符串“t2”会在“t1”字符串打印出来4秒后再打印出来,这时我们就说method1和method2是同步的。

    如果method2去掉了synchronized关键字,那么“t1”字符串和“t2”字符串几乎是同时打印出来的,这时我们就说method1和method2是异步的。

    同步的原因是加锁后两个线程只有mo这一个对象锁。

  • 相关阅读:
    【codecombat】 试玩全攻略 第二章 边远地区的森林 一步错
    【codecombat】 试玩全攻略 第十八关 最后的kithman族
    【codecombat】 试玩全攻略 第二章 边远地区的森林 woodlang cubbies
    【codecombat】 试玩全攻略 第二章 边远地区的森林 羊肠小道
    【codecombat】 试玩全攻略 第十七关 混乱的梦境
    【codecombat】 试玩全攻略 第二章 边远地区的森林 林中的死亡回避
    【codecombat】 试玩全攻略 特别关:kithguard斗殴
    【codecombat】 试玩全攻略 第二章 边远地区的森林 森林保卫战
    【codecombat】 试玩全攻略 第二章 边远地区的森林
    实验3 类和对象||
  • 原文地址:https://www.cnblogs.com/sigm/p/6120317.html
Copyright © 2011-2022 走看看