一、 Java并发编程
多任务、多进程、多线程的前提都是要求操作系统提供多任务、多进程、多线程的支持。操作系统的多进程实现了多任务并发执行,程序的多线程实现了进程的并发执行。
线程并发
当多个线程同时运行时,这种执行模式称为并发执行。在Java程序中,JVM负责线程的调度。线程调度是指按照特定的机制为多个线程分配CPU的使用权。
调度模式
- 分时调度:所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间。
- 抢占式调度:根据线程的优先级别来获取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

最低0.47元/天 解锁文章
170万+

被折叠的 条评论
为什么被折叠?



