天天看点

多线程安全问题----同步代码块

多线程安全问题

1.1解决线程安全问题的基本思想

(1)原因:当程序的多条语句在操作线程共享数据时(如买票例子中的票就是共享资源),

由于线程的随机性导致,一个线程对多条语句,执行了一部分还没执行完,另一个线程抢夺

到cpu 执行权参与进来执行,此时就导致共享数据发生错误。比如买票例子中打印重票和

错票的情况。

(2)解决方法:对多条操作共享数据的语句进行同步

首先想为什么出现问题?(也是我们判断是否有问题的标准)

  是否是多线程环境

  是否有共享数据

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

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

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

怎么实现呢?

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

.2Java 中多线程同步是什么?

同步是用来解决多线程的安全问题的,在多线程中,同步能控制对共享数据的访问。

如果没有同步,当一个线程在修改一个共享数据时,而另外一个线程正在使用或者更新同一

个共享数据,这样容易导致程序出现错误的结果。

1.3什么是锁?锁的作用是什么?

锁就是对象, 锁的作用是保证线程同步,解决线程安全问题。

持有锁的线程可以在同步中执行,没有锁的线程即使获得cpu 执行权,也进不去。

1.4同步的前提

(1)必须保证有两个以上线程

(2)必须是多个线程使用同一个锁,即多条语句在操作线程共享数据

(3)必须保证同步中只有一个线程在运行

1.5. 同步的好处和弊端

好处:同步解决了多线程的安全问题

弊端:多线程都需要判断锁,比较消耗资源

1.6解决线程安全问题实现1

(1)同步代码块:

可以指定需要获取哪个对象的同步锁,使用synchronized 的代码块同样需要锁,但

他的锁可以是任意对象,考虑到安全问题,一般还是使用同一个对象,相对来说效率较高。

注意:

虽然同步代码快的锁可以使任何对象,但是在进行多线程通信使用同步代码快时,

必须保证同步代码快的锁的对象和,否则会报错。

同步方法的锁是this,也要保证同步方法的锁的对象和调用wait、notify 和

notifyAll 的对象是同一个对象,也就是都是this 锁代表的对象。

格式:

synchronized(对象){需要同步的代码;}

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

同步代码块的对象可以是哪些呢?

下面就电影院买票问题进行说明:

package java.thread;

/**
 * 线程同步
 */
public class ThreadDemo4 {
	public static void main(String[] args) {
		Saler s1 = new Saler("s1",1);
		Saler s2 = new Saler("s2",1);
		s1.start();
		s2.start();
	}
}

/**
 * 售票员
 */
class Saler extends Thread {
	//总票数
	private static int tickets = 100 ;

	private String name0;

	private int sleep;

	public Saler(String name0, int sleep) {
		this.name0 = name0;
		this.sleep = sleep;
	}

	public String getName0() {
		return name0;
	}

	public void setName0(String name0) {
		this.name0 = name0;
	}

	public void run() {
		try {
			while(true){
				int temp = 0 ;
				synchronized (Saler.class){
					temp = tickets ;
					Thread.sleep(50);
					tickets -- ;
				}
				if(temp <= 0 ){
					return ;
				}
				else{
					System.out.println(name0 +" : " + temp);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
           

继续阅读