Java同步方法与同步语句的对比
来源:互联网 发布:折半查找的递归算法 编辑:程序博客网 时间:2024/06/16 06:21
众所周知,使用synchronized关键词实现同步的方式有两种:同步方法和同步语句。同步方法相对简单,但不够灵活;同步语句不仅能够避免在同步代码中调用其他对象的方法,从而减少死锁的可能性,而且能实现更细粒度的同步。
下面用程序来说明同步语句的两个优势。
1.避免在同步代码中调用其它对象的方法。考虑下面的程序:public class DeadLock implements Runnable { private Foo f1; private Foo f2; public DeadLock(Foo f1, Foo f2) { this.f1 = f1; this.f2 = f2; } public void run() { synchronized(f1) { try { // 增加死锁的可能性 Thread.sleep(1000); } catch (InterruptedException e) { } f2.bar(); } // f2.bar(); } public static void main(String[] args) { Foo f1 = new Foo(); Foo f2 = new Foo(); new Thread(new DeadLock(f1, f2)).start(); new Thread(new DeadLock(f2, f1)).start(); } private static class Foo { public void bar() { synchronized(this) { } } }}
程序运行后,就产生了一个死锁。这个死锁产生的原因是:在同步代码中调用了其他对象的方法。将f2.bar()移到同步代码之外,就可以避免这个死锁。使用同步方法对整个方法进行同步,显然不具备这种灵活性。
2.实现细粒度的同步
假设一个对象有两个域c1和c2,这两个域互不相关,为了提高并发度,我们需要对这两个域各自实现同步。也就是说,一个线程在访问c1时,另一个线程不能访问c1,但可以访问c2。细粒度同步通过减少不必要的阻塞,提高了并发度。下面的程序证明了这一点:
FineGrainedSynTest.java
public class FineGrainedSynTest { public static void main(String[] args) throws Exception { int numOfThreads = 100; if (args.length > 0) { numOfThreads = Integer.parseInt(args[0]); } NormalInc ni = new NormalInc(); FasterInc fi = new FasterInc(); Thread[] threads1 = new Thread[numOfThreads]; for (int i = 0; i < threads1.length; i++) { threads1[i] = new Thread(new IncTask(ni)); } ThreadsTimer tt1 = new ThreadsTimer(threads1); tt1.start(); Thread[] threads2 = new Thread[numOfThreads]; for (int i = 0; i < threads2.length; i++) { threads2[i] = new Thread(new IncTask(fi)); } ThreadsTimer tt2 = new ThreadsTimer(threads2); tt2.start(); System.out.format("普通并发对象耗时%dms,细粒度并发对象耗时%dms%n。", tt1.getDuration(), tt2.getDuration()); } private static class IncTask implements Runnable { Inc inc; public IncTask(Inc inc) { this.inc = inc; } public void run() { for (int i = 0; i < 100000; i++) { inc.inc1(); inc.inc2(); } } } private static interface Inc { public void inc1(); public void inc2(); } private static class NormalInc implements Inc { private long c1 = 0; private long c2 = 0; public void inc1() { synchronized(this) { c1++; } } public void inc2() { synchronized(this) { c2++; } } } private static class FasterInc implements Inc { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }}
ThreadsTimer.javaimport java.util.*;/* * ThreadsTimer用于统计一组线程从启动到结束的时间间隔 */public class ThreadsTimer { private Thread[] threads; // 线程们 private long duration; // 运行时间 public ThreadsTimer(Thread[] threads) { this.threads = threads; } public long getDuration() { return duration; } /* * 启动所有线程并开始计时。方法返回时,所有线程都已结束,且时间统计已完成。 */ public void start() throws InterruptedException { long start = System.currentTimeMillis(); for (Thread thread:threads) { thread.start(); } join(); duration = System.currentTimeMillis() - start; } /* * 当前线程频繁让出CPU时间片给待统计的线程,直到所有待统计的线程结束,从而使得统计更加准确 */ private void join() throws InterruptedException { ArrayList<Thread> liveThreads = new ArrayList<>(threads.length); for (Thread thread:threads) { if (thread.isAlive()) { liveThreads.add(thread); } } while (!liveThreads.isEmpty()) { // 随机选择一个存活线程,将时间片让给它 Random random = new Random(); int i = random.nextInt(liveThreads.size()); Thread t = liveThreads.get(i); if (t.isAlive()) { t.join(100); } else { liveThreads.remove(i); } } } }
程序的几次运行结果如下:
D:\Java\多线程性能测试>java FineGrainedSynTest 5
普通并发对象耗时259ms,细粒度并发对象耗时187ms
。
D:\Java\多线程性能测试>java FineGrainedSynTest 10
普通并发对象耗时516ms,细粒度并发对象耗时382ms
D:\Java\多线程性能测试>java FineGrainedSynTest 5
普通并发对象耗时259ms,细粒度并发对象耗时187ms
。
D:\Java\多线程性能测试>java FineGrainedSynTest 10
普通并发对象耗时516ms,细粒度并发对象耗时382ms
0 0
- Java同步方法与同步语句的对比
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java synchronized静态同步方法与非静态同步方法,同步语句块
- java类ThreadLocal与线程同步机制的对比
- java---同步调用与异步调用对比
- 同步块与同步方法的区别
- 同步方法与同步块的区别
- 同步块与同步方法的区别
- 同步方法与同步块的区别
- 同步方法与同步块的区别
- synchronized同步方法与同步语句块区别
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步方法
- Java线程:线程的同步-同步方法
- web模板引擎mustache
- mysql数据库优化技术(2)
- Linux下DNS配置
- 数据库存储过程(Procedure)
- Android入门(二):Android工程目录结构
- Java同步方法与同步语句的对比
- 杭电 HDU 1041 Computer Transformation
- 第2周项目2-长方柱类
- Logstash+syslog
- CF 523C (字符串处理)
- 黑马程序员————C语言——基础语法1
- 时间类
- centos7安装teamviewer 10 报error: unpacking of archive failed on file
- UVa 1344 - Tian Ji -- The Horse Racing(贪心)