多线程基础知识总结(二)
2018-01-26 17:59
316 查看
全文概要
本文主要介绍JAVA线程中synchronized关键字的用法。对于synchronized关键字主要包含以下几点:当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程不允许访问该对象synchronized修饰的相同的方法或者代码块;
当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程不允许访问该对象synchronized修饰的其他的非静态方法或者代码块;
当一个线程访问某一个对象synchronized修饰的方法或者代码块时,其他线程允许访问该对象的非synchronized修饰的方法或者代码块;
当一个线程访问某一个对象synchronized修饰的方法或者代码块时,其他线程允许访问其他对象synchronized修饰的非静态方法或者代码块;
当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程允许访问该对象synchronized修饰的静态方法或者代码块;
当一个线程访问同一个字节码对象的synchronized修饰的静态方法或者代码块时,其他线程不允许访问该节码对象的所有的synchronized修饰的静态方法或者代码块
synchronized关键字用法
验证第一点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo1 { public static void main(String[] args) { SynchronizedDemo1 demo = new SynchronizedDemo1(); Thread t1 = new Thread(new Runnable() { public void run() { demo.print(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { demo.print(); } }, "t2"); t1.start(); t2.start(); } private synchronized void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } 4000 } }
输出结果
t1 is running ....!
t1 is running ....!
t1 is running ....!
t1 is running ....!
t1 is running ....!
t2 is running ....!
t2 is running ....!
t2 is running ....!
t2 is running ....!
t2 is running ....!
结果说明
线程1和线程2都是调用SynchronizedDemo1对象的print()方法,线程1执行时,线程2阻塞。
验证第二点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo2 { public static void main(String[] args) { SynchronizedDemo2 demo = new SynchronizedDemo2(); Thread t1 = new Thread(new Runnable() { public void run() { demo.print(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { demo.read("hello world!"); } }, "t2"); t1.start(); t2.start(); } private synchronized void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } private synchronized void read(String name) { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is reading :" + name ); } catch (InterruptedException e) { e.printStackTrace(); } } } }
输出结果
t1 is running ....!
t1 is running ....!
t1 is running ....!
t1 is running ....!
t1 is running ....!
t2 is reading :hello world!
t2 is reading :hello world!
t2 is reading :hello world!
t2 is reading :hello world!
t2 is reading :hello world!
结果说明
线程1调用demo的print()方法,线程2调用demo的read()方法,虽然方法不同,但都是公用一个同步锁,所以线程1执行时,线程2阻塞。
验证第三点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo3 { public static void main(String[] args) { SynchronizedDemo3 demo = new SynchronizedDemo3(); Thread t1 = new Thread(new Runnable() { public void run() { demo.print(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { demo.write("hello world!"); } }, "t2"); t1.start(); t2.start(); } private void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } private synchronized void write(String name) { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is writing :" + name ); } catch (InterruptedException e) { e.printStackTrace(); } } } }
输出结果
t1 is running ....!
t2 is writing :hello world!
t2 is writing :hello world!
t1 is running ....!
t2 is writing :hello world!
t1 is running ....!
t1 is running ....!
t2 is writing :hello world!
t2 is writing :hello world!
t1 is running ....!
结果说明
print()方法为非同步方法,不会占用对象锁,所以线程1和线程2同时执行。
验证第四点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo4 { public static void main(String[] args) { SynchronizedDemo4 demo = new SynchronizedDemo4(); SynchronizedDemo4 demo1 = new SynchronizedDemo4(); Thread t1 = new Thread(new Runnable() { public void run() { demo.print(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { demo1.print(); } }, "t2"); t1.start(); t2.start(); } private synchronized void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
输出结果
t2 is running ....!
t1 is running ....!
t2 is running ....!
t1 is running ....!
t2 is running ....!
t1 is running ....!
t1 is running ....!
t2 is running ....!
t2 is running ....!
t1 is running ....!
结果说明
线程1和线程2的对象锁不一样,所以线程1和线程2同时执行。
验证第五点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo5 { public static void main(String[] args) { SynchronizedDemo5 demo = new SynchronizedDemo5(); Thread t1 = new Thread(new Runnable() { public void run() { /* * 调用非静态方法 */ demo.print(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { demo.staticPrint();//用对象调用静态方法,不规范,会有警告,建议用下面的方法 //SynchronizedDemo5.staticPrint(); } }, "t2"); t1.start(); t2.start(); } private synchronized void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is print running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } /* * 静态同步方法 */ private synchronized static void staticPrint(){ for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is staticPrint running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
输出结果
t2 is staticPrint running
....!
t1 is print running ....!
t2 is staticPrint running ....!
t1 is print running ....!
t1 is print running ....!
t2 is staticPrint running ....!
t2 is staticPrint running ....!
t1 is print running ....!
t1 is print running ....!
t2 is staticPrint running ....!
结果说明
线程1和线程2虽然都是调用demo对象的方法,但是print()为非静态同步方法,而staticPrint()为静态同步方法,根本原因
是对象锁不一样。非静态方法的同步锁为demo,而静态方法的同步锁为SynchronizedDemo5.class
验证第六点
代码案例package com.tml.javaCore.thread.sync; /** * <p>多线程 * @author Administrator * */ public class SynchronizedDemo6 { public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { public void run() { SynchronizedDemo6.staticPrint(); } }, "t1"); Thread t2 = new Thread(new Runnable() { public void run() { SynchronizedDemo6.staticPrint1(); } }, "t2"); t1.start(); t2.start(); } @SuppressWarnings("unused") private synchronized void print() { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is print running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } @SuppressWarnings("unused") private void print1() { synchronized (this) { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is print1 running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } } /* * 静态同步方法 */ private synchronized static void staticPrint(){ for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is staticPrint running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } private static void staticPrint1(){ /* * 静态同步代码块 */ synchronized (SynchronizedDemo6.class) { for(int i=0;i<5;i++){ try { Thread.sleep(500); System.out.println(Thread.currentThread().getName() + " is staticPrint1 running ....!"); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
输出结果
t1 is staticPrint running ....!
t1 is staticPrint running ....!
t1 is staticPrint running ....!
t1 is staticPrint running ....!
t1 is staticPrint running ....!
t2 is staticPrint1 running ....!
t2 is staticPrint1 running ....!
t2 is staticPrint1 running ....!
t2 is staticPrint1 running ....!
t2 is staticPrint1 running ....!
结果说明
对于静态方法,他的同步锁是该类的字节码对象,该对象在java内存中只有一份,例如,staticPrint()和staticPrint1()方法的同步锁一样。而非静态方法可以使用this来作为同步锁,this表示当前对象。例如,print()和print1()方法的同步锁一样。很多单例方法都使用字节码对象锁,确保该类只有一个实例。
相关文章推荐
- 多线程的实现基础知识总结
- Java多线程编程总结笔记——02多线程基础知识
- JAVA_SE ----- 基础知识总结-----多线程
- 多线程总结下篇(基础知识)
- 黑马程序员学习log第四篇基础知识:JAVA的面向对象之多线程总结
- 多线程基础知识总结(六)
- 多线程基础知识总结(四)
- Java多线程基础知识总结笔记
- 基础知识《四》---Java多线程学习总结
- 黑马程序员 Java基础知识总结-多线程
- Java基础知识总结:多线程
- Java多线程核心技术(一):基础知识总结
- java基础知识总结-多线程(二)
- Java多线程基础知识回顾与总结;
- 多线程基础知识总结(五)
- Java多线程基础知识总结笔记
- 多线程基础知识总结
- 多线程总结上篇(基础知识)
- Java多线程编程总结笔记——一多线程基础知识
- 多线程基础知识总结(三)