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);
}