同步块

本文通过示例介绍了如何使用同步块来减少同步范围,从而在保证线程安全的前提下提高程序的并发执行效率。通过控制同步代码块,可以精确地管理锁的作用范围。
/**
 * 有效的减少同步范围可以在保证安全的前提下提高并发效率
 * 控制同步的代码范围可以使用"同步块"
 * synchronized(同步监视器){
 *   需要同步的代码片段
 * }
 * 
 * 同步监视器:需要上锁的对象,若想保证具有同步效力,
 *          多个线程看到的应当是相同的对象。
 *          通常选取使用this即可。
 * @author Administrator
 *
 */
public class SyncDemo2 {
    public static void main(String[] args) {
        final Shop shop = new Shop();

        Thread t1 = new Thread(){
            public void run(){
                try {
                    shop.buy();
                } catch (Exception e) {
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                try{
                    shop.buy();
                }catch(Exception e){

                }
            }
        };
        t1.start();
        t2.start();
    }

}

class Shop{
    public void buy() throws Exception{
            Thread t = Thread.currentThread();
            System.out.println(t+"正在挑选衣服...");
            Thread.sleep(5000);

            synchronized (this) {
                System.out.println(t+"正在试衣服...");
                Thread.sleep(5000);
        }   

        System.out.println(t+"结账离开");
    }
}

运行结果:
Thread[Thread-0,5,main]正在挑选衣服...
Thread[Thread-1,5,main]正在挑选衣服...
Thread[Thread-0,5,main]正在试衣服...
Thread[Thread-0,5,main]结账离开
Thread[Thread-1,5,main]正在试衣服...
Thread[Thread-1,5,main]结账离开



<think>嗯,用户想了解Java中synchronized关键字在同步块中的用法,以及示例和注意事项。首先,我需要回忆一下synchronized的基本概念。根据引用[1],synchronized是Java的同步锁,解决多线程安全问题。同步块同步方法是两种使用方式,用户问的是同步块,所以重点要放在同步块上。 接下来,同步块的语法结构是怎样的呢?我记得同步块需要指定一个对象作为锁,通常是当前实例this或者类对象。例如synchronized (lockObject) { ... }。需要明确锁对象的选择,不同的锁对象会影响同步范围。比如,使用this的话,锁的是当前实例,而类对象的话,锁的是整个类。 然后,示例部分。引用[3]提到了修饰实例方法的例子,但用户需要的是同步块的示例。所以应该写一个使用同步块的代码,比如在方法内部使用synchronized块来同步特定代码段。比如,在实例方法中,用synchronized(this)包围需要同步的代码。或者静态方法中用synchronized(ClassName.class)。 注意事项方面,锁对象的选择很重要,不能选null或者可能被改变的对象。另外,同步块的作用域要尽量小,避免性能问题。还有死锁的问题,需要避免嵌套锁和不同顺序获取锁的情况。 用户可能还会关心与同步方法的区别。同步块更灵活,可以控制锁的粒度,而同步方法默认锁整个方法,可能锁的范围过大。另外,是否要处理异常,同步块内部如果抛出异常,锁会被释放,需要注意这一点。 需要检查是否有遗漏的注意事项,比如锁的可重入性,synchronized是可重入的,所以同一个线程可以多次获取同一把锁。还有同步块和volatile关键字的区别,但用户没问这个,可能不需要展开。 示例代码部分,可能需要两个例子,一个是实例方法的同步块,一个是静态方法的。比如第一个例子用this作为锁,第二个用类对象。这样用户可以看到不同情况下的应用。 最后,相关问题部分,要生成几个相关问题,比如与同步方法的区别,如何避免死锁,锁对象的选择等。根据用户提供的引用,可能还需要结合其他知识点,比如性能优化,或者最佳实践。 总之,回答需要结构清晰,先介绍同步块的语法,然后给出示例,再列出注意事项,最后相关问题。确保引用正确的来源,比如引用[2]提到同步方法的机制,可以对比说明同步块的灵活性。</think>### Java中synchronized关键字在同步块中的使用 #### 1. 同步块的基本语法 synchronized同步块通过显式指定锁对象来实现同步控制,语法如下: ```java synchronized (锁对象) { // 需要同步的代码块 } ``` 锁对象可以是任意非空对象,通常选择`this`(当前实例)或`类名.class`(类级别锁)[^3]。 --- #### 2. 同步块使用示例 ##### 示例1:实例方法中使用同步块 ```java public class Counter { private int count = 0; private final Object lock = new Object(); // 专用锁对象 public void increment() { synchronized (lock) { // 锁定特定对象 count++; } } } ``` **说明**: - 使用专用对象`lock`作为锁,避免与外部代码的锁冲突 - 仅同步`count++`关键操作,缩小同步范围[^2] ##### 示例2:静态方法中使用类级别锁 ```java public class Logger { public static void log(String message) { synchronized (Logger.class) { // 类级别锁 System.out.println(LocalDateTime.now() + ": " + message); } } } ``` **说明**: - 类级别锁通过`类名.class`实现 - 确保不同实例的静态方法调用也保持同步 --- #### 3. 关键注意事项 1. **锁对象选择**: - 必须是非空对象(避免`NullPointerException`) - 推荐使用专用私有锁对象(如示例1的`lock`) - 避免使用`String`等常量池对象可能导致意外锁竞争 2. **作用域控制**: ```java // 不推荐:同步范围过大 synchronized (this) { readFile(); processData(); // 耗时操作 updateDB(); } // 推荐:仅同步必要部分 Data data = readFile(); synchronized (this) { updateSharedResource(data); } ``` 3. **死锁防范**: - 避免嵌套获取多个锁 - 若必须获取多个锁,应保持一致的获取顺序 - 使用`tryLock()`等超时机制(需配合`Lock`接口) 4. **性能优化**: - 同步块应尽量简短(理想情况下<100ms) - 避免在同步块中执行I/O操作或复杂计算 --- #### 4. 同步块 vs 同步方法 | 特性 | 同步块 | 同步方法 | |--------------------|---------------------------------|-----------------------------| | 锁控制粒度 | 可自定义锁对象 | 默认`this`或`类名.class` | | 代码范围 | 精确到代码块级别 | 整个方法 | | 灵活性 | 高(可分段加锁) | 低 | | 锁泄露风险 | 较低(作用域明确) | 较高(方法可能提前返回) | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值