zoukankan      html  css  js  c++  java
  • 并发编程(一)—— 线程基础

    1.1 基础

    一、概念

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

    二、synchronized

    可以在任意对象及方法上加锁,而加锁的这段代码称为“互斥区”或“临界区”。

    三、示例

    【com.xxy.thread01】My Thread

     1 package com.xxy.thread01;
     2 
     3 public class MyThread extends Thread{
     4     private int count = 5;
     5     
     6     public synchronized void run() {
     7         count--;
     8         System.out.println(this.currentThread().getName() + " count=" + count);
     9     }
    10     
    11     public static void main(String[] args) {
    12         /*
    13          * 分析:当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排队是按照CPU分配的先后顺序而定的)
    14          *      一个线程想要执行synchronized修饰的方法里的代码:
    15          *      1. 尝试获得锁
    16          *      2. 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程会不断的尝试获得这把锁,直到拿到为止。
    17          *         而且是多个线程同时去竞争这把锁(这就是会有锁竞争的问题)。 
    18          */
    19         MyThread myThread = new MyThread();
    20         Thread t1 = new Thread(myThread, "t1");
    21         Thread t2 = new Thread(myThread, "t2");
    22         Thread t3 = new Thread(myThread, "t3");
    23         Thread t4 = new Thread(myThread, "t4");
    24         Thread t5 = new Thread(myThread, "t5");
    25         t1.start();
    26         t2.start();
    27         t3.start();
    28         t4.start();
    29         t5.start();
    30     }
    31 }
    View Code

    四、示例总结

    当多个线程访问My Thread的run方法时,以排队的方式进行处理(这里排队是按照CPU分配的先后顺序而定的),一个线程想要执行synchronized修饰的方法里的代码,首先是尝试获得锁,如果拿到锁,执行synchronized代码体内容:拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)。

     1.2 多个线程多个锁

    一、概念

    多个线程多个锁:多个线程,每个线程都可以拿到自己指定的锁,分别获得锁之后,执行synchronized方法体的内容。

    二、示例:【com.xxy.sync002】MultiThread

     1 package com.xxy.thread01;
     2 
     3 public class MultiThread {
     4     /*static*/
     5     private int number = 0;
     6     /*static*/
     7     public synchronized void print(String tag){
     8         if(tag.equals("a")) {
     9             number = 100;
    10             System.out.println("tag a set over");
    11             try {
    12                 Thread.sleep(1000);
    13             } catch (InterruptedException e) {
    14                 // TODO Auto-generated catch block
    15                 e.printStackTrace();
    16             }
    17         } else {
    18             number = 200;
    19             System.out.println("tab b set over");
    20         }
    21         System.out.println("tag "+ tag +"number = " + number);
    22     }
    23     
    24     public static void main(String[] args) {
    25         final MultiThread m1 = new MultiThread();
    26         final MultiThread m2 = new MultiThread();
    27         
    28         Thread t1 = new Thread(new Runnable() {
    29             
    30             @Override
    31             public void run() {
    32                 m1.print("a");
    33             }
    34         });
    35         
    36         Thread t2 = new Thread(new Runnable() {
    37             
    38             @Override
    39             public void run() {
    40                 m2.print("b");
    41             }
    42         });
    43         
    44         t1.start();
    45         t2.start();
    46     }
    47 }
    View Code

    三、示例总结

    关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当作锁,所以示例代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),两个对象,线程获得的就是两个不同的锁,他们互不影响。有一种情况则是相同的锁,即在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class)

    1.3 对象锁的同步和异步

    一、概念

    同步:synchronized

    同步的概念就是共享,我们要牢牢记住“共享”这两个字,如果不是共享的资源,就没有必要进行同步。

    异步:asynchronized

    异步的概念就是独立,相互之间不受任何制约。就好像我们学习http的时候,在页面发起的Ajax请求,我们还可以继续浏览或操作页面的内容,两者之间没有任何关系。

    同步的目的就是为了线程安全,其实对于线程来说,需要满足两个特性:原子性(同步)、可见性。

    二、示例【com.xxy.sync003】MyObject

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

    三、示例总结:

    A线程先持有Object对象的Lock锁,B线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步。

    A线程现持有Object对象的Lock锁,B线程可以以异步的方式调用对象中的非synchronized修饰的方法。

  • 相关阅读:
    Linux终端以及bash
    初识VIM
    基础命令
    目录结构和命令
    Xshell连接Centos7.5和yum
    Linux的发展史和centos7的安装
    学习方法以及计算机硬件基础
    mysql、MariaDB的简单操作
    yum 软件管理器
    基础面试题
  • 原文地址:https://www.cnblogs.com/upyang/p/13642798.html
Copyright © 2011-2022 走看看