线程安全问题:
在java中可以通过同步机制解决线程安全机制
方式一:synchronized(同步监视器){}
1.使用同步代码块解决实现Runnable接口的类的线程安全的问题:
- 使用关键字synchronized
synchronized(同步监视器){
需要被同步的代码(操作共享数据的代码)
}
-
同步监视器:又名“锁”。任何一个类的对象都可以充当一个锁
-
对"锁"的要求:多个线程必须共用同一把锁,也就是说,这把锁必须写在run()的外面。一般使用Object obj = new Object();
例如:
Object obj = new Object();
run(){
synchronized(obj){
需要被同步的代码
}
}
- 补充:在通过接口实现线程的类中,最方便的同步监听器就是this
例如:
run(){
synchronized(this){
需要被同步的代码
}
}
- 局限性:效率低,执行同步代码时,只能一个线程参与,其他线程要等待期结束后才能参与
2.使用同步代码块解决继承Thread类的方式的线程问题:
- 因为多个线程必须共用同一把锁,所以要用static来修饰 obj
例如:
Object static obj = new Object();
run(){
synchronized(obj){
需要被同步的代码
}
}
- 补充:不能使用this代替obj。但是可以使用 类.class 代替 obj(推荐)
例如:
class A extends Thread{
run(){
synchronized(A.class){
需要被同步的代码
}
}
}
注意:为了记忆方便,统一使用static来修饰obj,或者直接使用“当前所在类的类名.class”代替“同步监视器”
例如:
class A implements Runnable{
Object static obj = new Object();
run(){
synchronized(obj){
需要被同步的代码
}
}
}
class A extends Thread{
Object static obj = new Object();
run(){
synchronized(obj){
需要被同步的代码
}
}
}
class A implements Runnable{
run(){
synchronized(A.class){
需要被同步的代码
}
}
}
class A extends Thread{
run(){
synchronized(A.class){
需要被同步的代码
}
}
}
方式二、同步方法
public void run(){
method();
}
- 对于通过接口Runnable实现的多线程,如果操作共享数据的代码声明在一个方法中,那么我们就可以将此方法声明为同步的
例如:
priavte synchronized void method(){
需要被同步的代码
}
- 对于通过继承Thread实现的多线程,要把同步方法设为静态的,但是静态的方法中只能条用静态的方法
所以如果你想要使用Thread中的方法,就不能直接使用this.方法名()来调用,要是用Thread.currentThread().方法名()来调用
例如:
priavte static synchronized void method(){
需要被同步的代码
}
补充:为了方面记忆,在使用同步方法时,就都设置static synchronized关键字来修饰