单任务多线程 安全

线程状态

线程安全

   如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的

买票例子

原理图:

代码:

package com.oracle.Demo03;

public class Tickets implements Runnable{
	//把线程的共享数据做成成员变量
	private int tickets=100;
	//锁对象
	private Object mutex=new Object();
	public void run() {
		while(true){
			//同步代码快解决线程安全问题
			synchronized (mutex) {
				if (tickets>0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"售出第"+
				tickets--+"张票");
				}
			}
			
		}
	}

}
package com.oracle.Demo03;

public class Demo01 {

	public static void main(String[] args) {
		//创建创建线程任务
		Tickets03 t=new Tickets03();
		//创建3个线程对象
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		Thread t3=new Thread(t);
		//开启线程
		t1.start();
		t2.start();
		t3.start();
	}

  不安全原理图

线程同步(线程安全处理Synchronized)

线程同步的方式有两种:

  方式1:同步代码块

  方式2:同步方法

同步代码块: 在代码块声明上 加上synchronized

同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。

public class Ticket implements Runnable {
	//共100票
	int ticket = 100;
	//定义锁对象
	Object lock = new Object();
	@Override
	public void run() {
		//模拟卖票
		while(true){
			//同步代码块
			synchronized (lock){
				if (ticket > 0) {
					//模拟电影选坐的操作
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "正在卖票:" + ticket--);
				}
			}
		}
	}

  

同步方法

  同步方法:在方法声明上加上synchronized    

  同步方法中的锁对象是 this

package com.oracle.Demo03;

public class Tickets02 implements Runnable {
	// 把线程的共享数据做成成员变量
	private int tickets = 100;

	public void run() {
		while (true) {

			sale();

		}
	}
	//同步方法
	//StringBuffer 慢 所有方法都是同步方法 安全
	//StringBuilder 快  所有方法都是非同步方法   不安全
	public synchronized void sale(){
		if (tickets > 0) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "售出第" + tickets-- + "张票");

		}
	}

}
package com.oracle.Demo03;

public class Demo01 {

	public static void main(String[] args) {
		//创建创建线程任务
		Tickets03 t=new Tickets03();
		//创建3个线程对象
		Thread t1=new Thread(t);
		Thread t2=new Thread(t);
		Thread t3=new Thread(t);
		//开启线程
		t1.start();
		t2.start();
		t3.start();
	}

}

  注意:StringBuffer 慢 所有方法都是同步方法 安全
        StringBuilder 快  所有方法都是非同步方法   不安全

Lock接口

Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能

package com.oracle.Demo03;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Tickets03 implements Runnable{
	//把线程的共享数据做成成员变量
	private int tickets=100;
	private Lock lock=new ReentrantLock();
	private Object mutex=new Object();
	public void run() {
		while(true){
			lock.lock();
				if (tickets>0) {
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName()+"售出第"+
				tickets--+"张票");
				lock.unlock();
			}
			
		}
	}

}

  

原文地址:https://www.cnblogs.com/zqy6666/p/12320590.html