当然会产生错乱的结果,没有进行同步,就会产生。要想不产生错乱的结果,必须在进入临界区前加锁。静态方法虽然是属于整个类共享,只是代码共享,有可能传递不同的参数给静态方法。给段代码你参考。 public class TTT implements Runnable{ static class A{ static void f(int n){ for(int i=n;i<1000+n;i++) System.out.print("good"+n); } } int n; TTT(int x){n=x;} public void run(){ A.f(n); } public static void main(String[] args){ new Thread(new TTT(0)).start(); new Thread(new TTT(1000)).start();
package com.keeya.test; import keeya.util.*;public class ThreadTest extends Thread { public static int i = 0 , j = 0 ; public void run() { i++; j++; Test.test(i, j); } public static void main(String[] args) { Thread thread1 = new ThreadTest(); Thread thread2 = new ThreadTest(); Thread thread3 = new ThreadTest(); Thread thread4 = new ThreadTest(); Thread thread5 = new ThreadTest(); Thread thread6 = new ThreadTest(); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread6.start(); }
} class Test { public static void test(int i,int j){ MyOwnerPrint.println("This is {0} and i = {1}, j = {2}",Thread.currentThread(),i,j); int temp = 100000000; while(temp-- > 0); MyOwnerPrint.println("This is {0} and i + j = {1}",Thread.currentThread(),i+j); } } 这是我的测试代码 结果: This is Thread[Thread-1,5,main] and i = 2, j = 2This is Thread[Thread-3,5,main] and i = 4, j = 4This is Thread[Thread-2,5,main] and i = 3, j = 3This is Thread[Thread-0,5,main] and i = 1, j = 1 This is Thread[Thread-5,5,main] and i = 6, j = 6This is Thread[Thread-4,5,main] and i = 5, j = 5 This is Thread[Thread-2,5,main] and i + j = 6 This is Thread[Thread-4,5,main] and i + j = 10 This is Thread[Thread-5,5,main] and i + j = 12 This is Thread[Thread-0,5,main] and i + j = 2 This is Thread[Thread-3,5,main] and i + j = 8 This is Thread[Thread-1,5,main] and i + j = 4
打印结果是: Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-1 good 100 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 Thread-0 good 0 这个打印结果我没明白,为什么会这样?能否告之,而出现错乱结果是指的这个吗?
测试代码:package com.keeya.test; import keeya.util.*;public class ThreadTest extends Thread { public static int i = 0 , j = 0 ; public void run() { i++; j++; test(i, j); }
public void test(int i,int j){ MyOwnerPrint.println("This is {0} and i = {1}, j = {2}",Thread.currentThread(),i,j); int temp = 100000000; while(temp-- > 0); MyOwnerPrint.println("This is {0} and i + j = {1}",Thread.currentThread(),i+j); }
public static void main(String[] args) { Thread thread1 = new ThreadTest(); Thread thread2 = new ThreadTest(); Thread thread3 = new ThreadTest(); Thread thread4 = new ThreadTest(); Thread thread5 = new ThreadTest(); Thread thread6 = new ThreadTest(); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread6.start(); }
}结果: This is Thread[Thread-1,5,main] and i = 2, j = 2This is Thread[Thread-3,5,main] and i = 4, j = 4This is Thread[Thread-2,5,main] and i = 3, j = 3This is Thread[Thread-0,5,main] and i = 1, j = 1This is Thread[Thread-4,5,main] and i = 5, j = 5This is Thread[Thread-5,5,main] and i = 6, j = 6This is Thread[Thread-1,5,main] and i + j = 4 This is Thread[Thread-5,5,main] and i + j = 12 This is Thread[Thread-2,5,main] and i + j = 6 This is Thread[Thread-3,5,main] and i + j = 8 This is Thread[Thread-0,5,main] and i + j = 2 This is Thread[Thread-4,5,main] and i + j = 10 这个结果输出的格式是因为我自己写的那个MyOwnerPrint.println()方法导致的。 从结果可以看出我的MyOwnerPrint.println方法都被打断成2部分执行的 线程是安全的。
《深入解析windows操作系统-Windows Internals》 《Windows核心编程》
这里我想问一下,如果一个类的成员变量声明不是static的,它也是被所有线程所共享的吗,它不会复制到线程自己独立的运行空间中去吗?如下:public class Test { private int i;//这是成员变量
public static void test(){
} }和public class Test { private static int i;//这是成员变量
不过我知道的是,如果是多线程,不管是static还是非static
都会牵扯到一个 同步 的问题。
---
就这个代码而言,不会产生混淆。因为PrintStream的方法有线程同步的方法有static关键字和没有static 关键字的时候对多线程运行有没有影响
---
没有任何影响
public class TTT implements Runnable{
static class A{
static void f(int n){
for(int i=n;i<1000+n;i++)
System.out.print("good"+n);
}
}
int n;
TTT(int x){n=x;}
public void run(){
A.f(n);
} public static void main(String[] args){
new Thread(new TTT(0)).start();
new Thread(new TTT(1000)).start();
}
}
JAVA线程会在创建线程栈,在自己的空间里执行.可以访问父线程上下文的资源
如果多线程执行时涉及到资源共享 就可能会产生混乱 需要进行同步
参数都是在线程内部传进去的
每个线程调用这个方法的时候
都是将方法和参数压到各自的栈中(我记得我老师说过线程都是各有一个栈)
他们相互之间的属性没有耦合
package com.keeya.test;
import keeya.util.*;public class ThreadTest extends Thread {
public static int i = 0 , j = 0 ;
public void run() {
i++;
j++;
Test.test(i, j);
}
public static void main(String[] args) {
Thread thread1 = new ThreadTest();
Thread thread2 = new ThreadTest();
Thread thread3 = new ThreadTest();
Thread thread4 = new ThreadTest();
Thread thread5 = new ThreadTest();
Thread thread6 = new ThreadTest();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
}
}
class Test { public static void test(int i,int j){
MyOwnerPrint.println("This is {0} and i = {1}, j = {2}",Thread.currentThread(),i,j);
int temp = 100000000;
while(temp-- > 0);
MyOwnerPrint.println("This is {0} and i + j = {1}",Thread.currentThread(),i+j);
}
}
这是我的测试代码
结果:
This is Thread[Thread-1,5,main] and i = 2, j = 2This is Thread[Thread-3,5,main] and i = 4, j = 4This is Thread[Thread-2,5,main] and i = 3, j = 3This is Thread[Thread-0,5,main] and i = 1, j = 1
This is Thread[Thread-5,5,main] and i = 6, j = 6This is Thread[Thread-4,5,main] and i = 5, j = 5
This is Thread[Thread-2,5,main] and i + j = 6
This is Thread[Thread-4,5,main] and i + j = 10
This is Thread[Thread-5,5,main] and i + j = 12
This is Thread[Thread-0,5,main] and i + j = 2
This is Thread[Thread-3,5,main] and i + j = 8
This is Thread[Thread-1,5,main] and i + j = 4
打印结果是:
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-1 good 100
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
Thread-0 good 0
这个打印结果我没明白,为什么会这样?能否告之,而出现错乱结果是指的这个吗?
/*
*这里是自己写的一些业务,做了一些逻辑操作,处理一些数据
*
/
System.out.println(i+j);
}
加同步
import keeya.util.*;public class ThreadTest extends Thread {
public static int i = 0 , j = 0 ;
public void run() {
i++;
j++;
test(i, j);
}
public void test(int i,int j){
MyOwnerPrint.println("This is {0} and i = {1}, j = {2}",Thread.currentThread(),i,j);
int temp = 100000000;
while(temp-- > 0);
MyOwnerPrint.println("This is {0} and i + j = {1}",Thread.currentThread(),i+j);
}
public static void main(String[] args) {
Thread thread1 = new ThreadTest();
Thread thread2 = new ThreadTest();
Thread thread3 = new ThreadTest();
Thread thread4 = new ThreadTest();
Thread thread5 = new ThreadTest();
Thread thread6 = new ThreadTest();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
}
}结果:
This is Thread[Thread-1,5,main] and i = 2, j = 2This is Thread[Thread-3,5,main] and i = 4, j = 4This is Thread[Thread-2,5,main] and i = 3, j = 3This is Thread[Thread-0,5,main] and i = 1, j = 1This is Thread[Thread-4,5,main] and i = 5, j = 5This is Thread[Thread-5,5,main] and i = 6, j = 6This is Thread[Thread-1,5,main] and i + j = 4
This is Thread[Thread-5,5,main] and i + j = 12
This is Thread[Thread-2,5,main] and i + j = 6
This is Thread[Thread-3,5,main] and i + j = 8
This is Thread[Thread-0,5,main] and i + j = 2
This is Thread[Thread-4,5,main] and i + j = 10
这个结果输出的格式是因为我自己写的那个MyOwnerPrint.println()方法导致的。
从结果可以看出我的MyOwnerPrint.println方法都被打断成2部分执行的
线程是安全的。
《Windows核心编程》
这里我想问一下,如果一个类的成员变量声明不是static的,它也是被所有线程所共享的吗,它不会复制到线程自己独立的运行空间中去吗?如下:public class Test { private int i;//这是成员变量
public static void test(){
}
}和public class Test { private static int i;//这是成员变量
public static void test(){
}
}我想问一下这两个成员变量都是被所有线程共享的吗?还有我想问一下到底什么样的变更或者方法是被所有线程共享的,因为一旦被所有线程共享的话,就会有多线程并发的问题。
但是与同步的锁有关。
如果是static,则加锁的时候是类锁,实例方法则是实例锁。照你写的代码,无论多少个线程调用这个方法,都不会有同步问题的。
因为每个线程都在自己的线程栈中运行,局部变量会在各个栈中分别分配空间,互不干涉。
如果你使用了没加锁的全局变量,则会有问题。
public static void main(String[] args) {
Queue q=new Queue ();//new出一个q:后面的两个线程都是用的同一个q,保证一个put一个get
Producer p=new Producer (q);//让new出的p去往q里面put
Customer c=new Customer (q);//让new出的c从q中get
p.start();//p和q开始的顺序并不报错
c.start();
}
}
class Producer extends Thread
{
Queue q;
public Producer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的put方法
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
q.put(i);//此处只是让q去put 10次
System.out.println("Producer put "+i);//并且输出本次放的是第几杯
}
}
}
class Customer extends Thread
{
Queue q;
public Customer(Queue q) {
this.q=q;//给成员变量赋值,再一调运q的get方法
}
@Override
public void run() {
while (true) {//死循环:只要q里面有,就去get
//get方法有返回值,返回值就是producer所put的数量
//此处也不需要去考虑是第几杯
//在Queue中的value解决可这一问题:
//put中的I赋给value,get方法有返回值就value的值
System.out.println("Customer get "+q.get());
//如果循环完了,就跳出循环,否则线程不会自己结束
if (q.value==9) {
break;
}
}
}
}
class Queue
{
int value;
boolean bFull=false;
public synchronized void put (int i)//在producer中的put方法中就是将其I传进来
{
if (!bFull) {//条件为真(如果没满,就倒水)
value=i;//给value赋值,现在有几杯水
bFull=true;//满了
notify();//唤醒其他线程(让customer去get)
}
try {
wait();//告诉customer去get后自己等待customer的get结束
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized int get()
{
if (!bFull) {//如果没满就等待,如果满了就不进 **这就是为什么main里面谁先开始不报错的原因**
//get和put方法中的if条件判断起到了至关重要的作用
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
bFull =false;//赋值为没满
notify();//唤醒producer去put
return value;//get的返回值就是put的时候给value赋的值
}
}
static的方法是没有办法引用到非static的成员的。
问:什么时候会有线程同步问题呢?
答:几个线程使用同一个变量时。只有这个情况才会。在static方法里,只要所有的变量都是私有的(局部变量),那么永远不会出现什么线程同步问题。