java线程互斥是为了保证,同一时刻最多只有一个线程执行该段代码。那么它的出现又是为了解决什么问题呢?账户存取款,在同一时间段只能让一个人进行操作。
下面来看一个简单实例(多线程带来的问题):
public class TraditionalThreadSynchronized {
/**
* @param args
*/
public static void main(String[] args) {
new TraditionalThreadSynchronized().init();
}
private void init(){
//此方法同时启动两个线程,去调用同一个方法的打印名字
final Outputer outputer = new Outputer();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output3("lihuoming");
}
}
}).start();
}
static class Outputer{
public void output(String name){
int len = name.length();
// synchronized (Outputer.class)
// {
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
// }
}
}
}
打印结果为:
解决以上问题:
添加synchronized的关键字,即解开注释即可。
打印结果:
总结:
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。即当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
注意:要互斥,必须让锁子是同一把。以上的demo中,两个线程都用的是同一个new出来的output,所以output就是同一个对象。
详细内容请参看博客[原]02____线程的同步(Synchronized)
简答说明:
public class Test implements Runnable {
public int cash = 100;
public synchronized void m() {
System.out.println("m查看账户,余额为"+cash);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cash = cash - 100;
System.out.println("cash1 = " + cash);
}
public synchronized void run() {
System.out.println("run查看账户,余额为"+cash);
cash += 1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("cash2 = " + cash);
}
public static void main(String[] args) {
Test test = new Test();
Thread thrad = new Thread(test);
thrad.start();
test.m();
}
}
添加synchronized关键字后可以看出。只要m或者run进行对账户进行操作,不论中途多长时间,或者睡眠多长时间,线程都要执行完这个方法以后才会执行其他的方法。两个方法都必须加synchronized关键字,并且两者锁定同一对象(此处锁定的对象是test对象)。也就是说,只要有一个线程进入test对象的任意一个加了锁的方法,其他线程就不能访问这个对象里加了相同锁的方法了。