使用synchronized代码块及其原理?
使用synchronized方法?
分析静态方法所使用的同步监视器对象是什么?
一、代码实现
1、同一对象锁
/** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO* @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */package com.lh.threadtest.t3;import java.util.concurrent.TimeUnit;/** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术* @author Liu* @date 2018年1月15日 下午6:38:24 * */public class TraditionalThreadSynchronized { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { new TraditionalThreadSynchronized().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("lisi"); } } }).start(); } class Outputer{ public void output(String name){ String xxx = "xxx"; //不行,可以认为是不同的钥匙,不能起到互斥的效果// synchronized (name) {// for(int i = 0; i< name.length(); i++){// System.out.print(name.charAt(i));// }// System.out.println();// }// synchronized (this) { synchronized (xxx) { for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } }}
2、外部调用对象(锁)不同
/** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO* @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */package com.lh.threadtest.t3;import java.util.concurrent.TimeUnit;/** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术* @author Liu* @date 2018年1月15日 下午6:38:24 * */public class TraditionalThreadSynchronized2 { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { new TraditionalThreadSynchronized2().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }// outputer.output("lisi"); //改成下面这种方式也是不行的(外部调用的对象不是同一个)!!! new Outputer().output("lisi"); } } }).start(); } class Outputer{ public void output(String name){ String xxx = "xxx"; //不行,可以认为是不同的钥匙,不能起到互斥的效果// synchronized (name) {// for(int i = 0; i< name.length(); i++){// System.out.print(name.charAt(i));// }// System.out.println();// }// synchronized (this) { synchronized (xxx) { for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } }}
3、方法加synchronized关键字
/** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO* @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */package com.lh.threadtest.t3;import java.util.concurrent.TimeUnit;/** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术* @author Liu* @date 2018年1月15日 下午6:38:24 * */public class TraditionalThreadSynchronized3 { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { new TraditionalThreadSynchronized3().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("lisi"); } } }).start(); } class Outputer{ //方法名前加synchronized关键字!对整个方法体加锁! public synchronized void output(String name){ //线程间是互斥的!! for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } }}
4、代码块synchronized修饰(与3所加的锁都是this(外部调用对象))
/** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO* @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */package com.lh.threadtest.t3;import java.util.concurrent.TimeUnit;/** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术 (对象锁必须保证唯一性,即保证线程互斥性)* @author Liu* @date 2018年1月15日 下午6:38:24 * */public class TraditionalThreadSynchronized4 { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { new TraditionalThreadSynchronized4().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output2("lisi"); } } }).start(); } class Outputer{ //方法名前加synchronized关键字!对整个方法体加锁! public void output(String name){ synchronized (this) { for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } //方法名前的synchronized使用的锁默认是当前对象! public synchronized void output2(String name){ //线程间是互斥的!! for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } }}
5、静态方法static加synchronized关键字(锁必须是Outputer.class)
/** * @Title: TraditionalThreadSynchronized.java * @Package com.lh.threadtest * @Description: TODO* @author Liu * @date 2018年1月15日 下午6:38:24 * @version V1.0 */package com.lh.threadtest.t3;import java.util.concurrent.TimeUnit;/** * @ClassName: TraditionalThreadSynchronized * @Description: 传统线程互斥技术 (对象锁必须保证唯一性,即保证线程互斥性)* @author Liu* @date 2018年1月15日 下午6:38:24 * */public class TraditionalThreadSynchronized5 { /*** * @Title: main * @Description: TODO * @param @param args * @return void * @throws */ public static void main(String[] args) { new TraditionalThreadSynchronized5().init(); } private void init(){ final Outputer outputer = new Outputer(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output("zhangsan"); } } }).start(); new Thread(new Runnable() { public void run() { while(true){ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } outputer.output3("lisi"); } } }).start(); } static class Outputer{ //方法名前加synchronized关键字!对整个方法体加锁! public void output(String name){ synchronized (Outputer.class) { for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } } //方法名前的synchronized使用的锁默认是当前对象! public synchronized void output2(String name){ //线程间是互斥的!! for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } //静态方法名前的synchronized使用的是class对象! public static synchronized void output3(String name){ //线程间是互斥的!! for(int i = 0; i< name.length(); i++){ System.out.print(name.charAt(i)); } System.out.println(); } }}
二、注意点
1、内部类的作用:可以访问外部类的成员属性