0 代码案例:
package thread;
public class SynchronizedThread {
/**
* 利用打印姓名方法 测试多线程并发执行出现的问题
* 多线程下操作同一资源,如果不带锁下,必定出现争抢资源而结果显示异常错误,
*
* 任何对象都可以当做是一个门栓,如果要保持同步锁,那么门栓也要是同一个
*/
public static void main(String[] args) {
//final Outputer outputer = new Outputer();
//final Outputer1 outputer = new Outputer1();
final Outputer2 outputer = new Outputer2();
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out("zhong guo ren");
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.out("jieta car");
}
}
});
thread2.start();
}
}
// 下面写法是表达 一定要找出 那个共同的门栓 ,这才是 多线程下达到同步的 要点,至于是同步放在方法头上 还是放在方法体中,没有很大区别!!!!!
// 没有门栓下 多线程操作统一资源 出现打印名称错乱现象
class Outputer {
public void out(String name) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// 如下是同步代码块的两种写法
class Outputer1 {
String lock = "lock"; // 借助于第三方变量 来作为门栓
public void out(String name) {
synchronized (lock) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
class Outputer2 {
// 借助于调用者对象 来作为门栓 前提是调用者必须是同一个对象
public void out(String name) {
synchronized (this) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
// 如下是同步方法写法
class Outputer3 {
// 同步方法下,门栓是调用方法out的类Outputer3的对象,为了保证同步生效,必须确保不同线程调用此方法的类实例是同一个
// 此写法和 Outputer2的写法 是同样的效果
public synchronized void out(String name) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
// 如果 out方法是静态方法的话,那么同步代码块的门栓应该是 类对象
class Outputer4 {
// 同步方法下,门栓是调用方法out的类Outputer3的对象,为了保证同步生效,必须确保不同线程调用此方法的类实例是同一个
// 此写法和 Outputer2的写法 是同样的效果
public synchronized static void out(String name) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
// 在方法头上加同步 同时方法是static的 那么门栓只能是这个方法所在类的类字节码: !!!!!!!!!!!!!
/*public void out(String name) {
synchronized (Outputer4.class) {
int len = name.length();
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}*/
}
1 脑图: