1. 概述
Java中的线程表现为Threadclass,创建线程的唯一方式就是创建此类的一个实例对象。
使用Java代码有两种的方式(但最终都是创建一个Thread类实例)来创建一个线程:
- 继承Thread类:不必说,他就是Thread类的实例
- 实现Runable接口:使用时需要将实现类作为参数传递给一个Thread类的实例
2. 同步
Java提供了很多种线程之间通信的机制,最基本的一种就是 synchronization - 同步,这是通过 monitor - 监视器来实现的
首先,所有对象都关联着一个监视器,线程可以锁定或者解锁此监视器;
其次,且同一时间只能有一个线程可以锁定监视器,如果有其它线程想要尝试锁定的话它就会 block - 阻塞,直到它获得锁定权;
2.1 synchronized statement - 语句
synchronized 语句被执行时,会尝试去锁定其指定的对象上的监视器,直到成功为止;然后执行语句,最后自动解锁
语法:在synchronized (Expression) {}的Expression显示指定一个对象(最好的方式是实例语句中为this,类语句中为 类.class)
2.2 synchronized method - 方法
synchronized方法不同与语句的地方只在于其充当监视器的对象不能指定,而是只能按照默认规则来:实例语句中为this,类语句中为 类.class
2.3 deadlock - 死锁
Java语言不会阻止和检测死锁,程序如果需要避免死锁,应该使用自己保证
2.4 其它同步机制
volatile变量
任何被volatile修饰的变量,都不拷贝副本到工作内存,而是任何修改直接操作主内存。因此,对于volatile变量的修改,所有线程可以马上看到。但是,volatile不能保证线程们对变量的修改是有序的。很简单,比如说多个线程操作
volatile变量a时,public volatile int a; public void add(int b){ a = a + b; } //比如,a = 3,每个线程的b都是传1。 //1. 第一个线程来了,先进行3 + 1 记录,然后准备将4赋值给a时丢失CPU; //2. 第二个线程来了,也是3 + 1,然后赋值成功a等于4了。 //3. 第一个线程恢复CPU权,将4赋值给a。 //如上,其实正确结果无论线程一或二谁先执行,都应该是a = 5。但由于上述执行过程,a最终还是4,此时就是线程不安全。由于
a = a + b;并非是一个原子操作,所以有可能第一个线程执行到一半时停止而第二个线程开始执行。所以,
volatile适用的场景是有限的,总结如下:
可行必要条件- 对变量的写操作不依赖当前值。
- 变量没有包含在具有其它变量的不变式中。
其实由于
volatile只保证了可见性,所以其最符合直接赋值的场景。如上代码如果add方法内部只是a = b;即是。java.util.concurrent包中的类
对象、监视器、锁、线程的关系如下:
本文介绍了Java中线程的基本概念及其创建方式,并详细解析了线程同步机制,包括同步语句、同步方法及死锁等问题。此外还讨论了volatile变量的作用及限制,以及Java并发包提供的高级同步手段。

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



