线程安全问题及解决方法

3/8/2017来源:ASP.NET技巧人气:4979

(1)多线程安全问题的原因(也是我们判断一个程序是否有线程安全问题的依据)

A:是否有多线程环境

B:是否有共享数据

C:是否有多条语句操作共享数据

 

(2)如何解决多线程安全问题呢?

基本思想:让程序没有安全问题的环境。

怎么实现呢?

把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可(同步代码块)

(10)同步解决线程安全问题

A:同步代码块

   synchronized(对象){

   需要同步的代码;

   }

  

   a:对象是什么呢?

         可是是任意对象。

   b:需要同步的代码是哪些呢?

        把多条语句操作共享数据的代码的部分给包起来

  

   注意:

  同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。

  多个线程必须是同一把锁。

Eg:代码:

public class SellTicket implements Runnable {
// 定义100张票
PRivate int tickets = 100;
//创建锁对象
private Object obj = new Object();//也可以是任意对象
 
@Override
public void run() {
while (true) {
synchronized (obj) {  //不可以在这里new一个对象,因为我们要是同一把锁
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票");
}
}
}
}
}

 

B:同步方法

把同步加在方法上。

这里的锁对象是this//(默认的)

 

Eg:代码

 private synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}

C:静态同步方法

把同步加在方法上。

这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)//(默认SellTicket.class)

Eg:代码:

private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}

 

 

D:同步的特点

  1、同步的前提

多个线程

多个线程使用的是同一个锁对象

  2、同步的好处

同步的出现解决了多线程的安全问题。

  3、同步的弊端

当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。