Java 多线程访问方法

Java 多线程访问方法,java,Java,我正在学习多线程,我对一些事情有点困惑 比如说 public class Example{ public void function1(){ int toPrint = 0; System.out.println(toPrint); for(int i = 0; i < 10; i++) System.out.println("hello stackOverflow!"); } public syncrho

我正在学习多线程,我对一些事情有点困惑

比如说

public class Example{

   public void function1(){
        int toPrint = 0;
        System.out.println(toPrint);
        for(int i = 0; i < 10; i++)
        System.out.println("hello stackOverflow!");
   }
   public syncrhonized void function2(){
       ...
   }

}

public static void main(String[] args) {
            Example example = new Example();
            for (int i = 0; i < 10; i++) {
                RunningThread thread = new RunningThread(example);
                thread.start();
            }
        }
现在我不能显示图像,但我想清楚我的dubts,所以

如果我开始N个线程,我必须准备好这种情况

 _______________________________         ______________________________
|             thread1           |       |         thread..N            |
.................................       ................................
|            function1          |       |          function1           |
|          int toPrint = 0;     |       |        int toPrint = 0;      |
| System.out.println(toPrint);  |       |  System.out.println(toPrint);|
| for(int i = 0; i < 10; i++)   |       |  for(int i = 0; i < 10; i++) |
|    System.out.println();      |       |     System.out.println();    |
---------------------------------       --------------------------------
这样,每个线程
共享相同的函数和内容(例如,一个线程初始化值,另一个线程不初始化值),完成后,它们将等待执行锁定的
函数2()

始终遵守执行顺序,第一个功能1和第二个功能


对不起,如果这太长了,无论如何,谢谢。

< P>因为你同时做了<代码>函数1>代码>和<代码>函数2< /代码>代码>同步< /代码>没有线程可以在执行结束之前离开它们,所以在函数1的中间没有一个线程停止,另一个线程执行它的函数1或函数2。但是请注意,如果两个线程中都有相同的
run()
方法(我猜是这样),而第一个线程完成了
function1
,调度程序或调度程序可能会停止它并运行thread2,它可以完成两个函数调用,然后thread1可能会继续


< P> >强>注释< /强>:使用方法(),而不是函数(./p>>P>),因为你既做了代码<函数> 和<代码>函数2< /代码>代码>同步< /代码>没有线程可以在执行结束之前离开它们,所以在函数1的中间没有一个线程停止,另一个线程执行它的函数1或函数2。但是请注意,如果两个线程中都有相同的
run()
方法(我猜是这样),而第一个线程完成了
function1
,调度程序或调度程序可能会停止它并运行thread2,它可以完成两个函数调用,然后thread1可能会继续


注意:使用方法()而不是函数()。

synchronized关键字不会锁定函数,而是锁定对象,这意味着两个线程不能同时使用同一对象
synchronized void function 2
只是对

void function2(){synchronized(this){//
同步(即锁定对象)的原因是,任何线程都无法看到处于其不变量被破坏状态的对象。在您的示例中,类
example
没有状态,因此没有不变量,这意味着您不需要锁定它

您似乎关心的是
function2
的局部变量。但是,局部变量永远不会在线程之间共享,因此每个线程都有自己的局部变量实例


附录:如用户建议的那样,需要同步的示例如下:

考虑以下简单类:

public class Example {
    public int count = 0;

    public void increment() {
        count++;
    }

    public void decrement() {
        count--;
    }
}
这个类是可变的;其状态由
count
的值定义。如果客户机调用
递增
递减
,则状态应更改。这两种方法都有一个合同要遵守:

  • increment
    必须保证
    count
    的值是
    count
    的旧值加上一。让我们用
    count=old(count)+1来表示此合同

  • 同样地,
    减量的契约是
    count=old(count)-1

让我们依次运行这个类:

public static void main(String[] args) {
    Example sharedData = new Example();
    for (int i = 0; i < 1000; i++)
        sharedData.increment();
    System.out.println("Incrementer finished");
    for (int i = 0; i < 1000; i++)
        sharedData.decrement();
    System.out.println("Decrementer finished");
    System.out.println(sharedData.count);
}
我们可以随心所欲地运行代码,结果总是一样的

让我们定义多个线程,它们同时使用类
Example
的同一实例

public static void main(String[] args) throws InterruptedException {
    Example sharedData = new Example();
    Thread incrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                sharedData.increment();
            System.out.println("Incrementer finished");
        }
    });
    Thread decrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                sharedData.decrement();
            System.out.println("Decrementer finished");
        }
    });
    incrementer.start();
    decrementer.start();
    incrementer.join();
    decrementer.join();
    System.out.println(sharedData.count);
}
请注意,
递减器
计算的状态更改基于它读取的
计数
的值,即
0
,这意味着它没有看到
递增器
所做的状态更改

有多种方法可以解决此问题,但让我们试试
synchronized
关键字。我们可以通过锁定实例来禁止对
Example
的共享实例进行并发修改。因此,让我们修改我们的类:

public class Example {
    public int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }
}
让两个方法都锁定实例很重要,因为两个方法都不能看到处于不一致状态的对象

如果我们不能修改
示例的代码,例如,因为它是我们使用的库的一部分,该怎么办?我们如何使用
synchronized
关键字通过多个线程使用代码?如前所述,
synchronized void increment(){
void increment(){synchronized(this)
相同,因此同步不是方法的属性,而是对象。如果保持
Example
的代码不变,我们可以更改客户端:

public static void main(String[] args) throws InterruptedException {
    Example sharedData = new Example();
    Thread incrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                synchronized (sharedData){
                    sharedData.increment();
                }
            System.out.println("Incrementer finished");
        }
    });
    Thread decrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                synchronized (sharedData){
                    sharedData.decrement();
                }
            System.out.println("Decrementer finished");
        }
    });
    incrementer.start();
    decrementer.start();
    incrementer.join();
    decrementer.join();
    System.out.println(sharedData.count);
}
publicstaticvoidmain(String[]args)抛出InterruptedException{
示例sharedData=新示例();
线程递增器=新线程(new Runnable(){
@凌驾
公开募捐{
对于(int i=0;i<1000;i++)
已同步(共享数据){
sharedData.increment();
}
System.out.println(“增量完成”);
}
});
线程递减器=新线程(新可运行(){
@凌驾
公开募捐{
对于(int i=0;i<1000;i++)
已同步(共享数据){
sharedData.decrement();
}
System.out.println(“减量器完成”);
}
});
incrementer.start();
递减器。开始();
incrementer.join();
减量器。join();
System.out.println(sharedData.count);
}

synchronized关键字不锁定函数,而是锁定对象,这意味着两个线程不能同时使用同一个对象。
synchronized void function 2
只是语法糖

void function2(){synchronized(this){//
同步(即锁定对象)的原因是,没有线程可以看到对象处于其
incrementer enters increment and reads the value of count, count == 0
decrementer enters decrement and reads the value of count, count == 0
incrementer adds one and modifies the state, count == 1
decrementer subtracts one and modifies the state, count == -1 
public class Example {
    public int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }
}
public static void main(String[] args) throws InterruptedException {
    Example sharedData = new Example();
    Thread incrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                synchronized (sharedData){
                    sharedData.increment();
                }
            System.out.println("Incrementer finished");
        }
    });
    Thread decrementer = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 1000; i++)
                synchronized (sharedData){
                    sharedData.decrement();
                }
            System.out.println("Decrementer finished");
        }
    });
    incrementer.start();
    decrementer.start();
    incrementer.join();
    decrementer.join();
    System.out.println(sharedData.count);
}