zoukankan      html  css  js  c++  java
  • java线程的同步

    问题的引出

    在java语言中,我们常常会用到多线程相关的操作,但是多线程操作中可能会出现一些问题。

    现在给定一个抢票的多线程代码

    class MyThread implements Runnable{
    
        int a = 10;//票数
    
        @Override
    
        public void run()
    
        {
    
            while(true)
    
            {
    
                if(a>0)
    
                {
    
                    try {
    
                        Thread.sleep(1000);
    
                    } catch (InterruptedException e) {
    
                        e.printStackTrace();
    
                    }
    
                    System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a);
    
                }
    
                else
    
                {
    
                    System.out.println("票卖光了");
    
                    break;
    
                }
    
            }
    
        }
    
    }
    
    public class TheadOperation {
    
        public static void main(String[] args) throws InterruptedException {
    
            MyThread mt = new MyThread();
    
            new Thread( mt,"a1").start();
    
            new Thread(mt,"a2").start();
    
            new Thread( mt,"a3").start();
    
        }
    
    }

    这个代码通过a1,a2,a3三个线程来执行抢票的工作,但是当票数为1的时候,三个线程同时可以进入售票过程,--a会被执行,所以最终的票数将变成-2,这就是一个严重的错误,所以就需要线程同步了。

    什么是线程同步?

    首先,什么是线程同步?百度百科的回答是:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态,实现线程同步的方法有很多,临界区对象就是其中一种。

    通俗的来说就是多个操作在同一时间内,只能有一个线程进行,其他的线程要等此线程执行完了之后才可以继续执行。

    线程同步

    通过关键字synchronized来实现线程同步。

    可以有两种方法,一种是代码块形式,一种是关键字修饰方法的形式。

    首先给出代码块形式:

     1 class MyThread implements Runnable{
     2     int a = 1000000;
     3     @Override
     4     public void run()
     5     {
     6         while(true)
     7         {
     8             synchronized(this)
     9             {
    10                 if(a>0)
    11                 {
    12                     try {
    13                         Thread.sleep(1);
    14                     } catch (InterruptedException e) {
    15                         e.printStackTrace();
    16                     }
    17                     System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a);
    18                 }
    19                 else
    20                 {
    21                     System.out.println("票卖光了");
    22                     break;
    23                 }
    24             }
    25         }
    26     }
    27 }



    public class TheadOperation {
        public static void main(String[] args) throws InterruptedException {
            MyThread mt = new MyThread();
            new Thread( mt,"a1").start();
            new Thread(mt,"a2").start();
            new Thread( mt,"a3").start();
        }
    }

    synchronized(同步对象){代码操作}

    通过该操作,就完成了将代码块中的内容线程同步。

    然后是修饰方法:

    class MyThread implements Runnable{
    
        int a = 10000;
    
        public synchronized boolean abc()
    
        {
    
            if(a>0)
    
            {
    
                try {
    
                    Thread.sleep(1);
    
                } catch (InterruptedException e) {
    
                    e.printStackTrace();
    
                }
    
                System.out.println(Thread.currentThread().getName()+"买票。剩余票数"+ --a);
    
                return true;
    
            }
    
            else
    
            {
    
                System.out.println("票卖光了");
    
                return false;
    
            }
    
        }
    
        @Override
    
        public void run()
    
        {
    
            while(abc())
    
            {
    
            }
    
        }
    
    }
    
    
    
    public class TheadOperation {
    
        public static void main(String[] args) throws InterruptedException {
    
            MyThread mt = new MyThread();
    
            new Thread( mt,"a1").start();
    
            new Thread(mt,"a2").start();
    
            new Thread( mt,"a3").start();
    
        }
    
    }

    通过如此也可以实现方法体内线程同步。

    由于线程同步导致同一时间内只有一个线程可进行操作,其带来的一个问题就是开销大,会影响程序的性能,所以要谨慎使用。

  • 相关阅读:
    数据库笔记(mysql)(1)
    微擎框架商业版 V2.1.2 去后门一键安装版+去除云平台+无附带模块
    资深架构师Sum的故事:正则!入门就是这样简单
    人脸识别+大数据再结合面相学,看相一看一个准!
    layui里面的layer模块弹窗,强制居中的方法!!!
    抖音获取视频点赞数、播放数、获取用户粉丝列表
    破解微擎安装,免费搭建微擎,免费破解微擎,微擎破解版本,最新版本V2.1.2,一键安装!!
    资深架构师Sum的故事:(Mysql)InnoDB下,存储过程中事务的处理
    小程序开发教程:wx.setTopBarText(OBJECT)
    微信web协议,群成员唯一uin,获取群成员唯一标识
  • 原文地址:https://www.cnblogs.com/wu199723/p/12219573.html
Copyright © 2011-2022 走看看