java同步机制对象锁使用方式比较

class Sync {

    private byte[] lock = new byte[0];

    public void sync() throws InterruptedException {

        synchronized (lock) {
            runThread();
        }

    }

    public void thisSync() throws InterruptedException {

        synchronized (this) {
            runThread();
        }

    }

    public synchronized static void staticSync() throws InterruptedException { // 同步的static 函数
        runThread();
    }

    public void classSync() throws InterruptedException { //

        synchronized (Sync.class) {
            runThread();
        }
    }

    private static void runThread() throws InterruptedException {

        Thread current = Thread.currentThread();
        System.out.println("current thread id:" + current.getId() + "enter...");

        System.out.println("1111");
        Thread.sleep(1000);
        System.out.println("2222");
        Thread.sleep(1000);
        System.out.println("3333");
        Thread.sleep(1000);
        System.out.println("4444");
        Thread.sleep(1000);
        System.out.println("5555");

        System.out.println("current thread id:" + current.getId() + "out...");

    }

}

1.同一个线程lock对象锁是否可复用(即不用等待)

结论:可复用

public class TestObjectSyncLock {

    private static byte[] lock = new byte[0];//零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。 

    public static void main(String[] args) throws InterruptedException {

    //1.同一个线程lock对象锁是否可复用(即不用等待)----可复用

        synchronized (lock) {

            new Thread(new Runnable() {

                public void run() {

                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("aaa");

                }
            }).start();
            // lock.notify();
        }

        synchronized (lock) {

            System.out.println("bbb");
            // lock.wait();
        }
   }
}

结果:

bbb

aaa

2.同一个对象,多线程访问(一个主线程,一个新开线程)

结论:锁有效

  Thread current = Thread.currentThread();
       System.out.println("current thread id:"+current.getId()+"start...");
       final Sync sync =new Sync();

        new Thread(new Runnable() {

            public void run() {
                Thread current = Thread.currentThread();
                System.out.println("current thread id:"+current.getId()+"start...");
                try {
                    sync.sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }  

            }
        }).start();

        sync.sync();

结果:

current thread id:1start...

current thread id:1enter...

1111

current thread id:9start...

2222

3333

4444

5555

current thread id:1out...

current thread id:9enter...

1111

2222

3333

4444

5555

current thread id:9out...

3.不同对象,多线程访问

结论:锁无效

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        final Sync sync = new Sync();
        final Sync sync2 = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync2.sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.sync();

结果:

currret thread id:1start...

current thread id:1enter...

1111

currret thread id:9start...

current thread id:9enter...

1111

2222

2222

3333

3333

4444

4444

5555

current thread id:1out...

5555

current thread id:9out...

4.wait(),notify()----调用wait或notify时,该线程必须是该对象锁的所有者,否则会抛出Exception in thread "Thread-0" java.lang.IllegalMonitorStateException

 new Thread(new Runnable() {

            public void run() {

                System.out.println("------");
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    lock.notify();
                    System.out.println(" after notify ...");
                }
            }
        }).start();

        synchronized (lock) {

            System.out.println("enter ...");

            lock.wait();

            System.out.println("out ...");

        }

结果:

enter ...

------

after notify ...

out ...

5.wait(),notifyAll()----notifyAll()唤醒所有正在wait的不同线程

    new Thread(new Runnable() {

            public void run() {
                synchronized (lock) {
                    System.out.println("enter thread 1 ...");

                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("leave thread 1 ...");
                }
            }
        }).start();

        new Thread(new Runnable() {

            public void run() {
                synchronized (lock) {
                    System.out.println("enter thread 2 ...");

                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("leave thread 2 ...");
                }
            }
        }).start();

        new Thread(new Runnable() {

            public void run() {

                System.out.println("------");
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    lock.notifyAll();// notifyAll方法会唤醒所有正在等待对象控制权的线程。
                    // lock.notify();//随机通知一个正在等待的线程
                    System.out.println("after notifyAll ...");
                }
            }
        }).start();

结果:

enter thread 1 ...

enter thread 2 ...

------

after notifyAll ...

leave thread 2 ...

leave thread 1 ...

6.static 同步方法,不同对象

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        Sync sync = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Sync sync = new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.staticSync();// 锁有效
                    // Sync.staticSync();//锁有效
                    // sync.sync();//锁无效
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.staticSync();// 锁有效
        // Sync.staticSync();//锁有效
        // sync.sync();//锁无效

结果:

currret thread id:1start...

current thread id:1enter...

1111

currret thread id:9start...

2222

3333

4444

5555

current thread id:1out...

current thread id:9enter...

1111

2222

3333

4444

5555

current thread id:9out...

7.class 同步方法,不同对象

 Thread current = Thread.currentThread();
        System.out.println("currret thread id:" + current.getId() + "start...");
        Sync sync = new Sync();

        new Thread(new Runnable() {

            public void run() {
                Sync sync = new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.classSync();// 锁有效

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        sync.classSync();// 锁有效

结果:

currret thread id:1start...

current thread id:1enter...

1111

currret thread id:9start...

2222

3333

4444

5555

current thread id:1out...

current thread id:9enter...

1111

2222

3333

4444

5555

current thread id:9out...

8.this 同步方法,不同对象,跟2一样,对象锁

  final Sync sync = new Sync();
        new Thread(new Runnable() {

            public void run() {
                // Sync sync =new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.thisSync();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        new Thread(new Runnable() {

            public void run() {
                // Sync sync =new Sync();
                Thread current = Thread.currentThread();
                System.out.println("currret thread id:" + current.getId() + "start...");
                try {
                    sync.thisSync();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();

结果:

currret thread id:9start...

current thread id:9enter...

1111

currret thread id:10start...

2222

3333

4444

5555

current thread id:9out...

current thread id:10enter...

1111

2222

3333

4444

5555

current thread id:10out...

时间: 2024-08-30 06:37:16

java同步机制对象锁使用方式比较的相关文章

Java同步机制总结--synchronized

不久前用到了同步,现在回过头来对JAVA中的同步做个总结,以对前段时间工作的总结和自我技术的条理话.JAVA中synchronized关键字能够 作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.假如再细的分类,synchronized可作用于instance变 量.object reference(对象引用).static函数和class literals(类名称字面常量)身上. 在进一步阐述之前,我们需要明确几点: A.无论synchronized关键字加在方法上还

Java并发机制及锁的实现原理

Java并发编程概述 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最大限度地并发执行.在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战,比如上下文切换的问题.死锁的问题,以及受限于硬件和软件的资源限制问题,本章会介绍几种并发编程的挑战以及解决方案. 上下文切换 即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制.时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行

java——同步机制(synchronized, volatile)

1. java的线程间通信是由java的内存模型(JMM)来控制的. JMM(java memory management) 定义了线程和主内存之间的抽象关系,一个是主内存(多线程之间来进行共享),一个是每个线程自己的私有内存 2. 为什么需要同步机制? (1) 同步机制一般发生在多线程中,当需要跨线程维护程序的正确性,当需要多个线程之间共享非final变量时,就必须使用同步机制来保证一个线程的操作对于另一个线程是可见的 (2) 同步机制保证了多个线程之间的可靠通信,保证了多个线程之间对共享变量

【Thread】java线程之对象锁、类锁、线程安全

说明: 1.个人技术也不咋滴.也没在项目中写过线程,以下全是根据自己的理解写的.所以,仅供参考及希望指出不同的观点. 2.其实想把代码的github贴出来,但还是推荐在初学的您多亲自写一下,就没贴出来了. 一.基本说明 类.对象:...(不知道怎么说,只可意会不可言传>.<!):要明白哪些方法.变量是对象的,哪些是类的. 类锁.对象锁:对应类和对象.每个类有且仅有一个类锁,每个对象有且仅有一个对象锁. ex: Person p1 = new Person(); Person p2 = new

多线程-wait(针对OBJECT对象锁的方式)

对象锁,是 使用一个object 对象,将这个对象供多个线程共享使用,然后再线程中,对这个对象加锁. 直接看代码 package com.luoy.Thread.wait; public class ObjectWait2{ public static void main(String[] args) throws InterruptedException{ Object b = new Object(); Object c = new Object(); new Thread(new BuyF

Linux内核的同步机制---自旋锁

自旋锁的思考:http://bbs.chinaunix.net/thread-2333160-1-1.html 近期在看宋宝华的<设备驱动开发具体解释>第二版.看到自旋锁的部分,有些疑惑.所以来请教下大家. 以下是我參考一些网络上的资料得出的一些想法,不知正确与否.记录下来大家讨论下: (1) linux上的自旋锁有三种实现: 1. 在单cpu.不可抢占内核中,自旋锁为空操作. 2. 在单cpu,可抢占内核中,自旋锁实现为"禁止内核抢占".并不实现"自旋"

java同步机制:使用synchronize block,还是使用synchronize method

今天在学习java原子类的时候,遇到了这篇博客,看到了同步代码块和同步方法的区别,之前没有意识到,这里记录下. public class CP { private int i = 0; public synchronized int synchronizedMethodGet() { return i; } public int synchronizedBlockGet() { synchronized (this) { return i; } } } 从功能角度来说,上面两种方式没有差别,都能

Linux内核同步机制--自旋锁【转】

本文转载自:http://www.cppblog.com/aaxron/archive/2013/04/12/199386.html 自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名. 由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁. 信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进

Java对象锁和类锁全面解析(多线程synchronized关键字)

最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没用对都不知道. 今天把一些疑惑都解开了,写篇文章分享给大家,文章还算比较全面.当然可能有小宝鸽理解得不够深入透彻的地方,如果说得不正确还望指出. 看之前有必要跟某些猿友说一下,如果看一遍没有看明白呢,也没关系,当是了解一下,等真正使用到了,再回头看. 本文主要是将synchronized关键字用法作