Java:多个线程通过同步方法同时访问变量递减静态变量

标签 java multithreading static synchronization synchronized

我正在尝试同步我的 Person 类方法,以便我的静态计数器变量一次被一个线程递减。

public class Person extends Thread {

    private static int count = 10;

    public void decrement() {
        synchronized(Person.class) {
            count--;
        }

    }

    public int getCount() {
        return count;
    }

    public void run(){
        while( count > 0){
            this.decrement();
            System.out.print(this.getCount() + ",");
        }
    }
}

这是我的主课。每个线程将通过同步方法递减到静态计数器,以避免多个线程访问同一资源。

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Person p1 = new Person();
        Person p2 = new Person();
        Person p3 = new Person();
        Person p4 = new Person();
        Person p5 = new Person();

        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
    }
}

但是当我运行我的程序时,它正在打印重复的计数器值。我做错了什么?

输出:

8,8,7,6,5,4,3,2,1,0

8,7,5,3,1,0,6,8,4,0

最佳答案

原始代码中发生的事情如下:

  1. 线程一递减计数(计数 -> 9)
  2. 线程两次递减计数(计数 -> 8)
  3. 线程三个递减计数(count -> 7)
  4. 线程四递减计数(count -> 6)
  5. 线程一输出计数(计数:6)
  6. 线程两个输出计数(计数:6)
  7. 线程三个输出计数(计数:6)
  8. 线程四个输出计数(计数:6)

由于您锁定的是减量,而不是同时锁定减量和输出,因此它看起来会多次减量。

换句话说,不能保证这段代码会连续执行:

        this.decrement();
        System.out.print(this.getCount() + ",");

这是固定代码。它在递减时返回当前计数值,以便可以返回和打印新值。

public class Person extends Thread {

    private static int count = 10;

    public int decrement() {
        synchronized(Person.class) {
            count = count - 1;
            return count;
        }

    }

    public int getCount() {
        synchronized(Person.class) {
            return count;
        }
    }

    public void run(){
        while( getCount() > 0){
            int count = this.decrement();
            System.out.println(count);
        }
    }
}

不过我会推荐 AtomicInteger 来完成这项任务:

import java.util.concurrent.atomic.AtomicInteger;

public class Person extends Thread {

    private static AtomicInteger count = new AtomicInteger(10);

    public int decrement() {
        return count.decrementAndGet();
    }

    public void run(){
        while(count.get() > 0){
            int currentCount = this.decrement();
            System.out.print(currentCount + ",");
        }
    }
}

关于Java:多个线程通过同步方法同时访问变量递减静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36753028/

相关文章:

java - 图形 2d 对象的引用在孤立线程中不起作用

java - 获取与线程和数组列表相关的错误

multithreading - SQLITE3 CLSQL多线程插入导致错误

java - 静态数据是如何初始化的?

java - 方法引用静态与非静态

用于多时区应用程序的 java 日历、日期和时间管理

java - 带有路径注释的简单 REST 服务 - 404 错误

java - 格式化我的字符串

java - 如何让 Maven 从本地 Maven 项目构建依赖项而不是下载?

c++ - constexpr函数中的静态constexpr变量