多线程的互斥(synchronized关键字)
多线程操作同一个资源时会发生混乱的情况,而synchronized关键字能够有效的防止这种情况的发生。
比较普遍的例子:多人在同一时间存取同一账户的资金、以及项目中某些公共资源的访问和修改。
常见的用法:
1、在方法内锁定某一段语句
<span style="white-space:pre"> </span>private String symbol = "resource";
private void outPut(String str){
int len = str.length();
synchronized (symbol) {
for(int i =0;i<len;i++){
System.out.println(str.charAt(i));
}
System.out.println();
}
}
锁定的资源不能是基础的数据类型,一般是引用类型、String。
2、锁定整个方法
private synchronized void outPut1(String str){
int len = str.length();
for(int i =0;i<len;i++){
System.out.println(str.charAt(i));
}
System.out.println();
}
以上代码等价于
<span style="white-space:pre"> </span>private void outPut1(String str){
synchronized(this){
int len = str.length();
for(int i =0;i<len;i++){
System.out.println(str.charAt(i));
}
System.out.println();
}
}
2种写法锁定的都是this当前对象。
当在多个线程中,同一个Object调用outPut1()方法时,会检查当前的Object是否被锁定,如果锁定则会等待其它线程释放Object资源,否则直接执行方法outPut1();
还有一种常见的写法是锁定类的字节码
<span style="white-space:pre"> </span>class SynchronizedDemo{
private void outPut(String str){
synchronized(SynchronizedDemo.class){
int len = str.length();
for(int i =0;i<len;i++){
System.out.println(str.charAt(i));
}
System.out.println();
}
}
}
以上代码等价于
<span style="white-space:pre"> </span>class SynchronizedDemo{
private static synchronized void outPut(String str){
int len = str.length();
for(int i =0;i<len;i++){
System.out.println(str.charAt(i));
}
System.out.println();
}
}
不管是锁定类synchronized(Object.class)还是锁定类的对象synchronized(this),只需要注意那些可能会被更改的公共资源,如果程序中有多个入口来修改它,就考虑用synchronized关键字。