synchronized关键字

synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰构造器、属性等。

对synchronized(this)的一些理解
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的除synchronized(this)同步代码块以外的部分。
第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
以上规则对其它对象锁同样适用。

上述内容参考:http://hacker0825.blog.163.com/blog/static/3457067720106994054575/

一:synchronized同步代码块

package com.clzhang.sample.thread;

public class SyncThread1 implements Runnable {
    private Integer key = 0;

    @Override
    public void run() {
        // key是Integer对象(注意不是int,因为int不是对象)
        // 线程进入下面同步代码之前,需要先获取key的锁。
        // 需要结果是key实现自增长,如果没有同步块,则可能会出现重复key值的现象
        synchronized (key) {
            key++;

            System.out.println(Thread.currentThread().getName() + ":" + key);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }

    public static void main(String[] args) {
        SyncThread1 st = new SyncThread1();

        for(int i=0; i<10; i++) {
            new Thread(st, "Thread" + i).start();
        }
    }
}

输出:

Thread1:2
Thread3:3
Thread5:4
Thread7:5
Thread0:2
Thread2:7
Thread9:6
Thread4:8
Thread6:9
Thread8:10

二:synchronized同步方法
同步方法分静态和非静态两种。静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。

2.1 非静态方法同步示范

package com.clzhang.sample.thread;

// 如果是同步方法,则分静态和非静态两种。
// 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。
public class SyncThread2 implements Runnable {
    private Integer key = 0;

    // 此示范为非静态方法同步
    public synchronized Integer getKey() {
        key++;

        return key;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + getKey());
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
    }

    public static void main(String[] args) {
        // 非静态方法同步,需要启动单例模式
        SyncThread2 st = new SyncThread2();
        for (int i = 0; i < 10; i++) {
            new Thread(st, "Thread" + i).start();
        }
    }
}

输出:

Thread0:1
Thread1:3
Thread2:2
Thread3:5
Thread5:6
Thread7:7
Thread9:8
Thread6:9
Thread8:10
Thread4:4

2.2 静态方法同步示范

package com.clzhang.sample.thread;

// 如果是同步方法,则分静态和非静态两种。
// 静态方法则一定会同步,非静态方法需在单例模式才生效,推荐用静态方法(不用担心是否单例)。
public class SyncThread3 implements Runnable {
    private static Integer key = 0;

    // 此示范为静态方法同步
    public synchronized static Integer getKey() {
        key++;

        return key;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + ":" + getKey());
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
    }

    public static void main(String[] args) {

        // 如果用静态方法实现同步,则可以生成对象的多个实例
        for (int i = 0; i < 10; i++) {
            SyncThread3 st = new SyncThread3();
            new Thread(st, "Thread" + i).start();
        }
    }
}

输出:

Thread3:3
Thread1:1
Thread0:2
Thread5:4
Thread7:5
Thread9:6
Thread2:7
Thread8:10
Thread6:9
Thread4:8

总结 1、无论是同步代码块还是同步方法,必须获得对象锁才能够进入同步代码块或者同步方法进行操作。 2、如果采用方法级别的同步,对象锁为方法所在的对象;如果是静态同步方法,对象锁为方法所在的类(唯一)。 3、对于代码块,对象锁即指synchronized(object)中的object。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值