Java线程同步与并发:深入理解与实践

一、 Java并发编程

多任务、多进程、多线程的前提都是要求操作系统提供多任务、多进程、多线程的支持。操作系统的多进程实现了多任务并发执行,程序的多线程实现了进程的并发执行。

线程并发

当多个线程同时运行时,这种执行模式称为并发执行。在Java程序中,JVM负责线程的调度。线程调度是指按照特定的机制为多个线程分配CPU的使用权。

调度模式

  1. 分时调度:所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间。
  2. 抢占式调度:根据线程的优先级别来获取CPU的使用权。

JVM的线程调度模式采用了抢占式模式

“并发”与“同时”的真相

所谓的“并发执行”、“同时”其实都不是真正意义上的“同时”。

  • CPU都有个时钟频率,表示每秒中能执行 CPU指令的次数。在每个时钟周期内,CPU实际上只能去执行一条(也有可能多条)指令。
  • 操作系统将进程/线程进行管理,轮流(没有固定的顺序)分配每个进程很短的一段时间(不一定是均分),然后在每个线程内部,程序代码自己处理该进程内部线程的时间分配,多个线程之间相互的切换去执行,这个切换时间也非常短。
  • 因此多任务、多进程、多线程都是操作系统给人的一种宏观感受,从微观角度看,程序的运行是异步执行的。

明白什么时候应该使用并发,什么时候应该避免使用并发是非常关键的。使用它的原因主要是:要处理很多任务,它们交织在一起,能够更有效地使用计算机,能够更好地组织代码,或者更便于用户使用。

二、 线程同步

问题的引出

有时候在进行多线程的程序设计中需要实现多个线程共享同一些资源,比如,内存,文件,数据库等。这时,由于线程和线程之间无序地访问这些共享资源,最终可能导致无法得到正确的结果。

一个典型例子

模拟多线程车票销售系统,引出线程同步安全问题。

//源代码ThreadDemo1.java

public class ThreadDemo1{
	public static void main(String[] args){
		TestThread1 t = new TestThread1();
		//开启一个线程
		new Thread(t).start();
		//开启一个线程
		new Thread(t).start();
		//开启一个线程
		new Thread(t).start();
		//开启一个线程
		new Thread(t).start();
	}
}

class TestThread1 implements Runnable{
	//总票数是20张
	private int nTickets = 20;
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			// 休眠100-1000毫秒,用来模拟售票延迟
			try {
				Thread.sleep((int)((Math.random()*900)+100));
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			//如果还有票就卖票,否则break退出线程
			if (nTickets > 0) {
				try {
					// 休眠100-1000毫秒,用来模拟网络延迟
					Thread.sleep((int)((Math.random()*900)+100));
				} catch (InterruptedException e) {
					// TODO Auto-g
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ObjectHu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值