多线程访问内部类

我创建了3个正在访问ThreadsAroundInnerClasses外部类的内部类MyInnerClassThreadsAroundInnerClasses

package com.test;

public class ThreadsAroundInnerClasses {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread(), "THREAD-1");
        Thread t2 = new Thread(new MyThread(), "THREAD-2");
        Thread t3 = new Thread(new MyThread(), "THREAD-3");
        t1.start();
        t2.start();
        t3.start();
    }

    static class MyInnerClass {
        static int counter = 0;
        public void printIt(String threadName) {
            System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName);
        }
    }
}

class MyThread implements Runnable {
    @Override
    public void run() {
        ThreadsAroundInnerClasses.MyInnerClass innerObj = new ThreadsAroundInnerClasses.MyInnerClass();
        innerObj.printIt(Thread.currentThread().getName());
    }
}

在输出中,我可以看到MyInnerClass类中的counter静态变量没有按顺序更新。

I am inside inner class, counter value is 1 and thread name is THREAD-1
I am inside inner class, counter value is 3 and thread name is THREAD-2
I am inside inner class, counter value is 2 and thread name is THREAD-3

如果有人能解释如何在多线程的情况下处理内部类,那将会非常有帮助。 我们可以同步整个内部课堂吗?

先谢谢您的帮助。


班级是不是内部班级是无关紧要的。 你在这里看到的是预期的输出:你的程序中没有任何同步,并且线程调度程序因此可以随意切换到其他线程。 这里有一系列可能的操作,这会导致你看到的输出。

  • T1:增量计数器
  • T1:concaenate
  • T1:打印
  • T3:增量计数器
  • T3:连接
  • T2:增量计数器
  • T2:连接
  • T2:打印
  • T3:打印
  • 如果你想要计数器增量,连接和打印是一个原子操作,那么你应该确保它在一个唯一的锁上同步:

    synchronized MyInnerClass.class {
        System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName);
    }
    

    尝试这个:

        static class MyInnerClass {
        static int counter = 0;
        public void printIt(String threadName) {
            synchronized(MyInnerClass.class) {
                System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName);
            }
        }
    }
    

    你的计数器是静态的,所以你需要在整个类对象上进行同步。


    这是一个阅读 - 然后改变和线程可见性的问题

    读那么变化

    增量首先是读取,然后是添加,然后是回写。 ++countercounter = counter + 1简写,这意味着:“读取计数器,添加一个,将结果写回计数器”。 这个流程可以在另一个线程的中间被中断:Thread1读取计数器,得到1 - 并被中断。 线程2读取计数器 - 它仍然是1 - 增加1 - 并被中断。 线程3读取计数器 - 它仍然是1 - ....等等。 行为基本上是随机的。 只需在后台运行其他应用程序,您可能会激发不同的输出。

    线程可见性

    对于多核架构中的非易失性非同步变量,不同的线程可能在不同的内核上运行,并且内核可能会在其寄存器上缓存该变量。 这意味着一个线程可能无法看到另一个线程写入该变量 - 直到它被提交回内存并且有新的写入。

    同步是创造记忆障碍的一种方式。 系统将保证下次进行锁定时,写入锁内的所有内容均可见。 实际上 - 当你退出同步块时,你所做的每件事都被记录下来。 然后你进入同步块,所有内容都从内存中读回来。

    volatile关键字告诉系统禁止将变量缓存在寄存器中 - 它必须始终在内存中读写。 这使得每个人都阅读到最新的内容,但由于上述原因,这并不能解决您的问题。

    简单的解决方案

    解决您的特定问题的最简单方法是使用AtomicInteger。

    static class MyInnerClass {
        static final AtomicInteger counter = new AtomicInteger(0);
        public void printIt(String threadName) {
            System.out.println("I am inside inner class, counter value is " +
                counter.incrementAndGet() + " and thread name is " + threadName);
        }
    }
    

    这将为您节省所有同步的麻烦 - 它包含在AtomicInteger类中。

    链接地址: http://www.djcxy.com/p/92057.html

    上一篇: Multiple threads accessing inner class

    下一篇: Threads On Normal Vs Maximum Priority