前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Java中的静态同步方法

Java中的静态同步方法

作者头像
GeekLiHua
发布2025-01-21 16:50:19
发布2025-01-21 16:50:19
6700
代码可运行
举报
文章被收录于专栏:JavaJava
运行总次数:0
代码可运行

Java中的静态同步方法

简介

在Java中存在静态同步方法,也就是在静态方法上使用synchronized关键字。它的锁是当前类的Class对象,也就是说,每个类只有一个Class对象,在多线程下通过这种方式可以确保同一时间只能有一个线程进入到静态同步方法中执行代码,从而避免并发导致的数据错误和异常。

具体来说,当一个线程调用了一个被synchronized修饰的静态同步方法M时,JVM会尝试获取该类的Class对象的锁。如果该锁没有被其他线程持有,则当前线程可以获取该锁并执行M方法中的代码;否则,当前线程会阻塞等待其他线程释放锁。

下面是一个简单示例:

代码语言:javascript
代码运行次数:0
复制
public class Singleton{
    
    // 静态变量instance
    private static Singleton instance;
    
    // 私有构造方法
    private Singleton() {}
    
    // 静态同步方法getInstance
    public synchronized static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    // 其他方法
    public void doSomething() {
        // ...
    }
}

在上面的代码中,我们定义了一个Singleton类,并使用了静态变量instance和静态同步方法getInstance实现了单例模式。对于getInstance,我们添加了synchronized关键词,以确保线程安全地创建Singleton实例。其他方法doSomething则与此无关。

需要注意的是,在静态同步方法中,我们不能使用this关键字来获得锁,而应该使用当前类的Class对象,即Singleton.class。因为在Java中,每个类都对应着唯一的Class对象,因此这么做能够避免不必要的歧义和意外情况的发生。

案例

下面是一个静态同步方法的简单示例:

代码语言:javascript
代码运行次数:0
复制
public class Counter {
    
    private static int count = 0;
    
    // 增加count计数器并打印计数日志
    public static synchronized void increment() {
        count++;
        System.out.println("Count is now " + count);
    }
    
    // 获取计数器
    public static int getCount() {
        return count;
    }
}

在上述示例中,我们定义了一个Counter类,并添加了一个静态变量count、一个静态同步方法increment和一个静态方法getCount。在increment方法中,我们通过synchronized关键字保证了线程安全地自增计数器,并在控制台输出计数日志。而在getCount方法中,我们只需返回计数器的值,因此不需要使用synchronized关键字。

调用静态同步方法时,如果多个线程同时试图访问该方法,则会对类的Class对象进行锁定以避免竞争冲突,保证同一时间只有一个线程能够执行这个方法的代码块。从而保证了线程安全,避免了同步问题带来的数据错误和异常。

非常抱歉,我的上一个答案有误。因为在increment方法的执行结束之前,会一直占有锁,其他线程需要等待锁释放才能继续执行。因此,实际结果是顺序的,每个线程依次执行increment方法,并打印出相应的计数器值。

以下是更新后的样例代码及输出:

代码语言:javascript
代码运行次数:0
复制
public class Main {
    
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new CounterThread();
            thread.start();
        }
    }
    
    private static class CounterThread extends Thread {
        
        @Override
        public void run() {
            // 执行10次自增操作
            for (int i = 0; i < 10; i++) {
                Counter.increment();
            }
        }
    }
}

public class Counter {
    
    private static int count = 0;
    
    // 增加count计数器并打印计数日志
    public static synchronized void increment() {
        count++;
        System.out.println("Count is now " + count);
    }
    
    // 获取计数器
    public static int getCount() {
        return count;
    }
}

运行结果如下所示:

代码语言:javascript
代码运行次数:0
复制
Count is now 1
Count is now 2
Count is now 3
Count is now 4
Count is now 5
Count is now 6
Count is now 7
Count is now 8
Count is now 9
Count is now 10
Count is now 11
Count is now 12
Count is now 13
Count is now 14
Count is now 15
Count is now 16
Count is now 17
Count is now 18
Count is now 19
Count is now 20
...

可以看到,每个线程依次执行increment方法,并打印出相应的计数器值。由此可见,使用静态同步方法确实可以在多线程环境下保证线程安全,并避免竞争条件导致的数据错误和异常。

  • 回答问题:使用静态同步方法,可以让结果是顺序的吗
  • 回答: 使用静态同步方法确实可以保证多个线程访问该方法时是线程安全的,但并不意味着它能够保证结果是顺序的。

在上述示例中,每个线程都会执行increment方法10次,并打印出更新后的计数器值。由于每次调用increment方法都需要获取锁来保证线程安全,因此多个线程之间只有一个线程可以同时进行计数器的自增操作,其他线程需要等待到获得锁时才能继续执行。所以最终输出结果会按照入队和出队的顺序逐一打印出,而非是随机的乱序。

但如果不仅有静态方法,还在程序里面加入了其他的处理逻辑,比如读写文件等IO操作,可能会导致甚至语句执行的先后顺序和代码书写的先后顺序,也不一定对应输出结果的前后顺序。

综上所述,使用静态同步方法只能保证多个线程同时访问静态方法时互斥地执行其中的代码块,不能保证输出结果的顺序。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-09-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java中的静态同步方法
    • 简介
    • 案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档