java中多线程安全性和同步的常用方法

Posted wx6070687864c6e

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中多线程安全性和同步的常用方法相关的知识,希望对你有一定的参考价值。

1、多线程安全性问题,即多线程在什么场景下会出现异常?

多个线程同时调用一个共享的变量(对象),比如当某个线程操作车票的过程中,尚未操作完成时,其他线程参与进来,也操作车票。

 

2、在Java中,我们通过同步机制,来解决线程的安全问题。

3、有几种同步机制?

有3种,同步代码块、同步方法、Lock;

 

4、同步代码块

 代码如下:

synchronized(同步监视器)
//需要被同步的代码

注意:

(1)同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。要求:多个线程必须要共用同一把锁。同步监视器必须唯一,且是一个对象。也就是多个线程共享一个同步监视器对象。否则同步代码块不生效。

 (2)包裹的代码是操作共享数据的代码,即为需要被同步的代码。不能多,也不能少,否则就会出错。

(3)共享数据:多个线程共同操作的变量。

 (4)在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

(5)在继承Thread类创建多线程的方式中,慎用this充当同步监视器,考虑使用当前类充当同步监视器。也就是"类名.class",比如“Student.class”。

实例代码1(实现Runnable接口):

class Window1 implements Runnable

private int ticket = 100;
// Object obj = new Object();
// Dog dog = new Dog();
@Override
public void run()
// Object obj = new Object();
while(true)
synchronized (this)//此时的this:唯一的Window1的对象 //方式二:synchronized (dog)

if (ticket > 0)

try
Thread.sleep(100);
catch (InterruptedException e)
e.printStackTrace();


System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);


ticket--;
else
break;




View Code

实例代码2(继承Thread):

class Window2 extends Thread


private static int ticket = 100;

private static Object obj = new Object();

@Override
public void run()

while(true)
//正确的
// synchronized (obj)
synchronized (Window2.class)//Class clazz = Window2.class,Window2.class只会加载一次
//错误的方式:this代表着t1,t2,t3三个对象
// synchronized (this)

if(ticket > 0)

try
Thread.sleep(100);
catch (InterruptedException e)
e.printStackTrace();


System.out.println(getName() + ":卖票,票号为:" + ticket);
ticket--;
else
break;






View Code

 

5、同步方法

(1)同步方法仍然涉及到同步监视器,只是不需要我们显式的声明。

(2)非静态的同步方法,同步监视器是:this
  静态的同步方法,同步监视器是:当前类本身

实例代码1(实现Runnable接口)

class Window3 implements Runnable 

private int ticket = 100;

@Override
public void run()
while (true)

show();



private synchronized void show()//同步监视器:this
//synchronized (this)

if (ticket > 0)

try
Thread.sleep(100);
catch (InterruptedException e)
e.printStackTrace();


System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);

ticket--;

//

View Code

 

实例代码2(继承Thread)

class Window4 extends Thread 


private static int ticket = 100;

@Override
public void run()

while (true)

show();



private static synchronized void show()//同步监视器:Window4.class
//private synchronized void show() //同步监视器:t1,t2,t3。此种解决方式是错误的
if (ticket > 0)

try
Thread.sleep(100);
catch (InterruptedException e)
e.printStackTrace();


System.out.println(Thread.currentThread().getName() + ":卖票,票号为:" + ticket);
ticket--;


View Code

 

 

 

6、单例模式中懒汉模式的线程安全的代码:

lass Bank

private Bank()

private static Bank instance = null;

public static Bank getInstance()
//方式一:效率稍差
// synchronized (Bank.class)
// if(instance == null)
//
// instance = new Bank();
//
// return instance;
//
//方式二:效率更高
if(instance == null)

synchronized (Bank.class)
if(instance == null)

instance = new Bank();




return instance;


View Code

 

作者:沐雪 文章均系作者原创或翻译,如有错误不妥之处,欢迎各位批评指正。本文版权归作者,如需转载恳请注明。 如果您觉得阅读这篇博客让你有所收获,
​​​ 为之网-热爱软件编程 http://www.weizhi.cc/​

以上是关于java中多线程安全性和同步的常用方法的主要内容,如果未能解决你的问题,请参考以下文章

线程安全问题-synchronized(方法)火车票卖票代码演示

4-5 《Java中多线程重点》——继承Thread实现Runnable死锁线程池Lambda表达式

线程的同步机制:同步代码块&同步方法

java11_线程的同步

java线程详细介绍

同步方法和同步块