java线程的同步

Posted 不继

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();

    }

}

 

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

 

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

以上是关于java线程的同步的主要内容,如果未能解决你的问题,请参考以下文章

java基础入门-多线程同步浅析-以银行转账为样例

线程同步-使用ReaderWriterLockSlim类

Java多线程——Lock&Condition

Java多线程与并发库高级应用-工具类介绍

Java多线程与并发库高级应用-工具类介绍

Java多线程:线程同步详解