java多线程-synchronized
2016-03-31 17:37
399 查看
synchronized是Java中使用的最基本的一个同步方法,使用 synchronized关键字来控制并发访问方法。只有一个执行线程将会访问一个对象中被synchronized关键字声明的方法。如果另一个线程试图访问同一个对象中任何被synchronized关键字声明的方法,它将被暂停,直到第一个线程结束方法的执行。
每个方法声明为synchronized关键字是一个临界区,Java只允许一个对象执行其中的一个临界区。
静态方法有不同的行为。只有一个执行线程访问被synchronized关键字声明的静态方法,但另一个线程可以访问该类的一个对象中的其他非静态的方法。 你必须非常小心这一点,因为两个线程可以访问两个不同的同步方法,如果其中一个是静态的而另一个不是。如果这两种方法改变相同的数据,你将会有数据不一致 的错误。
同一个类中有多个synchronized关键字声明的静态方法。只要有一个线程访问了其中一个,其它线程则不可以访问任务一个synchronized关键字声明的静态方法,但可以访问该类其它同步方法和普通方法。
示例:
结果:
可以看到:
线程6与线程7 排队执行
线程3与线程6 没有排队
线程1与线程2 排队执行
线程1阻塞时,其它非静态方法都能顺利执行
每个方法声明为synchronized关键字是一个临界区,Java只允许一个对象执行其中的一个临界区。
静态方法有不同的行为。只有一个执行线程访问被synchronized关键字声明的静态方法,但另一个线程可以访问该类的一个对象中的其他非静态的方法。 你必须非常小心这一点,因为两个线程可以访问两个不同的同步方法,如果其中一个是静态的而另一个不是。如果这两种方法改变相同的数据,你将会有数据不一致 的错误。
同一个类中有多个synchronized关键字声明的静态方法。只要有一个线程访问了其中一个,其它线程则不可以访问任务一个synchronized关键字声明的静态方法,但可以访问该类其它同步方法和普通方法。
示例:
import java.util.Scanner; public class SynchronizedTest { public static synchronized void test1(){ System.out.println(Thread.currentThread().getName()+"进入阻塞!任意键结束!"); Scanner a = new Scanner(System.in); a.next(); } public static synchronized void test2(){ System.out.println(Thread.currentThread().getName()+"进入阻塞!任意键结束!"); Scanner a = new Scanner(System.in); a.next(); } public synchronized void test3(){ System.out.println(Thread.currentThread().getName()+"开始运行!"); System.out.println(Thread.currentThread().getName()+"请稍等..."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"运行结束!"); } public void test4(){ System.out.println(Thread.currentThread().getName()+"没有阻塞,运行结束!"); } public static void main(String[] args) { Thread a = new Thread(new Runnable(){ @Override public void run() { SynchronizedTest.test1(); } }); Thread b = new Thread(new Runnable(){ @Override public void run() { SynchronizedTest.test2(); } }); Thread c = new Thread(new Runnable(){ @Override public void run() { new SynchronizedTest().test3(); } }); Thread d = new Thread(new Runnable(){ @Override public void run() { new SynchronizedTest().test3();; } }); Thread e = new Thread(new Runnable(){ @Override public void run() { new SynchronizedTest().test4();; } }); final SynchronizedTest syn = new SynchronizedTest(); Thread f = new Thread(new Runnable(){ @Override public void run() { syn.test3();; } }); Thread g = new Thread(new Runnable(){ @Override public void run() { syn.test3();; } }); a.setName("线程1"); b.setName("线程2"); c.setName("线程3(与线程4不同对象的同一任务)"); d.setName("线程4(与线程3不同对象的同一任务)"); e.setName("线程5"); f.setName("线程6(与线程7同对象的同一任务)"); g.setName("线程7(与线程6同对象的同一任务)"); a.start(); b.start(); c.start(); d.start(); e.start(); f.start(); g.start(); } }
结果:
线程1进入阻塞!任意键结束! 线程4(与线程3不同对象的同一任务)开始运行! 线程4(与线程3不同对象的同一任务)请稍等... 线程6(与线程7同对象的同一任务)开始运行! 线程6(与线程7同对象的同一任务)请稍等... 线程3(与线程4不同对象的同一任务)开始运行! 线程3(与线程4不同对象的同一任务)请稍等... 线程5没有阻塞,运行结束! 线程4(与线程3不同对象的同一任务)运行结束! 线程6(与线程7同对象的同一任务)运行结束! 线程3(与线程4不同对象的同一任务)运行结束! 线程7(与线程6同对象的同一任务)开始运行! 线程7(与线程6同对象的同一任务)请稍等... 线程7(与线程6同对象的同一任务)运行结束! d 线程2进入阻塞!任意键结束! d
可以看到:
线程6与线程7 排队执行
线程3与线程6 没有排队
线程1与线程2 排队执行
线程1阻塞时,其它非静态方法都能顺利执行
相关文章推荐
- 使用 Syncthing 在多个设备间同步文件
- C#实现多线程的同步方法实例分析
- 科学知识:同步、异步、阻塞和非阻塞区别
- 同步文件备份工具 Super Flexible File Synchronizer Pro v4
- 探讨Ajax中同步与异步之间的区别
- C#线程同步的三类情景分析
- C++使用CriticalSection实现线程同步实例
- 探究在C++程序并发时保护共享数据的问题
- 基于C#实现的多生产者多消费者同步问题实例
- ASP.NET之自定义同步HTTP处理程序(图文教程)
- C#中线程同步对象的方法分析
- Nodejs实战心得之eventproxy模块控制并发
- Jquery ajax 同步阻塞引起的UI线程阻塞问题
- jQuery实现文本框输入同步的方法
- jQuery中$.ajax()和$.getJson()同步处理详解
- 并发环境下mysql插入检查方案
- MSSQL自动同步设置方法
- 一个进程间通讯同步的C#框架引荐
- jQuery中的ajax async同步和异步详解
- Java中使用synchronized关键字实现简单同步操作示例