Java多线程 volatile synchronized关键字

多线程

——一个程序可以包括多个子任务,可串行 / 并行

——每个子任务可称为一个线程

——如果一个子任务阻塞,程序可将CPU调度另一个子任务工作,确保CPU时间片获取率和使用时间

 

相较于多进程优势

——线程间共享数据

——线程间通讯更为高效

——线程是轻量级的,切换更为方便

——多个线程更易管理

 

Java多线程方法

——java.lang.Thread                          线程继承Thread类,实现run方法

——java.lang.Runnable接口              线程实现Runnable接口 实现run方法

两种方式对比

——Thread占据了父类的名额(由于Java的单继承机制),使得继承Thread类后无法继承其它类

——推荐方法实现Runnable接口 由Runnable接口初始化Thread

——Runnable更容易实现多线程中资源共享

多线程启动

——Thread.start()方法,线程启动(需要cpu时间片获得才进入运行态) 调用run方法

——直接调用run方法  那么run将作为普通函数执行,变成串行执行

——同一个线程 多次调用start方法将会报错

——线程在run方法执行结束后 自动关闭

——Main主函数线程可能早于子线程结束,但整个程序不会终止(所有线程执行完才终止)

 

Java默认提供的Thread多线程方法缺点

——粗粒度 子线程之间,与main主线程之间缺乏数据交流和控制

希望通过共享变量达到信息共享

——线程类的static变量为所有线程实例所共有

——同一个Runnable类的成员变量(用一个Runnable对象初始化多个Thread)达到共享

缺点  数据读写的不一致性

——工作缓存副本

——关键步骤缺乏加锁机制 

如一个i++操作  不是原子操作

(    原子操作是指不会被线程调度机制打断的操作;

        操作一旦开始,就一直运行到结束,中间不会有任何 切换)

——读取主存到各个线程的工作缓存

——CPU执行(副本)i++操作

——CPU将结果写入到缓存(副本)中

——数据从工作缓存(副本)刷到主存中

 

解决方案 volatile

——采用Java中volatile关键字修饰变量、一旦被修改 其它线程立即可见

——保证不同线程对共享变量操作的可见性

——当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存

——当有其他线程需要读取时,它会去内存中读取新值。

 

synchronized互斥关键字

——互斥表示同一时间只允许一个线程运行一个代码块

——同步表示各个线程必须按照一定先后顺序运行

——互斥是同步的一种特例

——synchronized关键字修饰函数 代码块 同一时间只允许一个线程执行该过程

——缺点 虽然操作简单 但效率低下加大性能负担

 

实例演示  多线程并发卖票问题

public class ThreadDemo0 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		new TestThread0().start();
		new TestThread0().start();
		new TestThread0().start();
		new TestThread0().start();
		

	}

}
class TestThread0 extends Thread
{
	private static int tickets=100;//static为所有线程所共享
	public void run()
	{
		while(true)
		{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName()+"is selling ticket "+tickets);
				tickets--;
			}
			else
			{
				break;
			}
		
		}
	}
}

 

在没有对共享变量tickets进行控制情况下,出现了数据读写不一致性  100编号的票被卖出去2次

 

 

 

采用volatile关键字进行控制

class TestThread0 extends Thread
{
	private  static volatile int tickets=100;//static为所有线程所共享
	public void run()
	{
		while(true)
		{
			if(tickets>0)
			{
				System.out.println(Thread.currentThread().getName()+"is selling ticket "+tickets);
				tickets--;
			}
			else
			{
				break;
			}
		
		}
	}
}

执行结果   各线程正确的卖完了100张票

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值