• 多线程解决同步问题浅析


    一,问题背景

    1.为什么要引入多线程?

         用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。

    2.多线程、同步、并发概念:

    多线程:指的是这个程序(一个进程)运行时产生了不止一个线程。
    并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
    并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

    3.引入多线程后会带来那些问题?

          java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。

    以买票系统为例,我们发现不加控制多线程会出现超卖现象。

     1 public class RunnableImpl implements Runnable {
     2 
     3 private int ticket=100;
     4     @Override
     5     public void run() {
     6         while(true){
     7             if (ticket<=0){
     8                 break;
     9             }
    10             try {
    11                 Thread.sleep(200);
    12                 String name = Thread.currentThread().getName();
    13                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    14             } catch (InterruptedException e) {
    15                 e.printStackTrace();
    16             }
    17 
    18         }
    19 
    20 
    21 
    22     }
    23 }

    测试类:

    1 public class originticket {
    2     public static void main(String[] args) {
    3         RunnableImpl runnable = new RunnableImpl();
    4        new Thread(runnable,"一").start();
    5        new Thread(runnable,"二").start();
    6     }
    7 }

    结果显示:

    二,问题解决方案之synchronize代码块:

     1 public class RunnableImplsyn implements Runnable {
     2 
     3 private int ticket=200;
     4     @Override
     5     public void run() {
     6         while(true) {
     7             try {
     8                 Thread.sleep(200);
     9             } catch (InterruptedException e) {
    10                 e.printStackTrace();
    11             }
    12             synchronized (this) {
    13             if (ticket <= 0) {
    14                 break;
    15             }
    16 
    17 
    18                     String name = Thread.currentThread().getName();
    19                     System.out.println("第" + name + "窗口正在卖出第" + (200 - ticket + 1) + "张票,剩余" + (--ticket) + "张");
    20 
    21 
    22             }
    23         }
    24 
    25 
    26     }
    27 }

    测试类:

    1 public class synchronizeblockTicket {
    2 
    3     public static void main(String[] args) {
    4         RunnableImplsyn runnableImplsyn = new RunnableImplsyn();
    5         new Thread(runnableImplsyn,"一").start();
    6         new Thread(runnableImplsyn,"二").start();
    7     }
    8 }

    结果:

    三,问题解决方案之synchronize方法:

    这里抽取了方法,this代指:

     1 public class RunnableImplsynfn implements Runnable {
     2 
     3 private static int ticket=200;
     4     @Override
     5     public void run() {
     6        test();
     7    
     8     }
     9 
    10 
    11     private synchronized void test() {
    12         while(true){
    13             if (ticket<=0){
    14                 break;
    15             }
    16             try {
    17                 Thread.sleep(200);
    18                 String name = Thread.currentThread().getName();
    19                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    20             } catch (InterruptedException e) {
    21                 e.printStackTrace();
    22             }
    23 
    24         }
    25 
    26 
    27 
    28     }
    29     }

    测试类:

    1 public class synchronizefnTicket {
    2 
    3 
    4     public static void main(String[] args) {
    5         RunnableImplsynfn runnableImplsyn = new RunnableImplsynfn();
    6         new Thread(runnableImplsyn,"一").start();
    7         new Thread(runnableImplsyn,"二").start();
    8     }
    9 }

    四,问题解决方案之静态synchronize方法:

    同上

     1 public class RunnableImplsynfn implements Runnable {
     2 
     3 private static int ticket=200;
     4     @Override
     5     public void run() {
     6         statictest();
     7 
     8     }
     9 
    10     private static synchronized void statictest() {
    11         while(true){
    12             if (ticket<=0){
    13                 break;
    14             }
    15             try {
    16                 Thread.sleep(200);
    17                 String name = Thread.currentThread().getName();
    18                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    19             } catch (InterruptedException e) {
    20                 e.printStackTrace();
    21             }
    22 
    23         }
    24 
    25     }
    26    
    27 
    28     }
    29     }

    测试类一样略。

    五,问题解决方案之lock方法:

     1 import java.util.concurrent.locks.Lock;
     2 import java.util.concurrent.locks.ReentrantLock;
     3 
     4 public class Runnablelock implements Runnable {
     5     private int ticket=200;
     6    Lock l= new ReentrantLock();
     7 
     8     @Override
     9     public void run() {
    10         while(true){
    11  /*       try {
    12         Thread.sleep(20);
    13         } catch (InterruptedException e) {
    14             e.printStackTrace();
    15         }*/
    16 l.lock();//从此以后加锁
    17 
    18             if (ticket<=0){
    19                 break;
    20             }
    21             try {
    22                 Thread.sleep(200);
    23 
    24                 String name = Thread.currentThread().getName();
    25                 System.out.println("第"+name+"窗口正在卖出第"+(200-ticket+1)+"张票,剩余"+(--ticket)+"张");
    26             } catch (InterruptedException e) {
    27                 e.printStackTrace();
    28             }finally {
    29                 l.unlock();//释放锁
    30             }
    31 
    32         }
    33 
    34 
    35     }
    36 }

    测试类:

    1 public class lockTicket {
    2 
    3 
    4     public static void main(String[] args) {
    5         Runnablelock runnablelock = new Runnablelock();
    6         new Thread(runnablelock,"一").start();
    7         new Thread(runnablelock,"二").start();
    8     }
    9 }
    当一个男人不再对你啰嗦,不再缠着你,不再没事找你,对你说话也客气了,也不再气你了。那么恭喜你,你已经成功的失去了他。别嫌弃男人幼稚,那是他喜欢你,爱你。女人说男人像小孩子一样不成熟,可又有谁知道,男人在自己喜欢的女人面前才像小孩子,如果不喜欢你了,不爱你了,他比你爸还成熟。
  • 相关阅读:
    spring filter and interceptor
    spring 与 swagger 2 的整合
    spring 异步操作
    图片延迟加载 jquery,lazyload.js 调用的demo
    一、Spring的第一个课时
    线程的基本了解
    HTTPS/HTTP监听常见问题
    Leetcode 118 杨辉三角
    HashSet的源码解释
    HashMap源码理解
  • 原文地址:https://www.cnblogs.com/fengtangjiang/p/11103595.html
Copyright © 2020-2023  润新知