永发信息网

java多线程并发去调用一个类的静态方法,会有问题吗?

答案:5  悬赏:80  手机版
解决时间 2021-03-07 01:03
java多线程并发去调用一个类的静态方法,会有问题吗?
最佳答案
总的结论:java是线程安全的,即对任何方法(包括静态方法)都可以不考虑线程冲突,但有一个前提,就是不能存在全局变量。如果存在全局变量,则需要使用同步机制。

如下通过一组对比例子从头讲解:
在多线程中使用静态方法会发生什么事?也就是说多线程访问同一个类的static静态方法会发生什么事?是否会发生线程安全问题?
public class Test {
public static void operation(){
// ... do something
}
}
事实证明只要在静态函数中没有处理多线程共享数据,就不存在着多线程访问同一个静态方法会出现资源冲突的问题。下面看一个例子:
public class StaticThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
StaticAction.print();
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new StaticThread()).start();
}
}
}
public class StaticAction {
public static int i = 0;
public static void print() {
int sum = 0;
for (int i = 0; i < 10; i++) {
System.out.print("step " + i + " is running.");
sum += i;
}
if (sum != 45) {
System.out.println("Thread error!");
System.exit(0);
}
System.out.println("sum is " + sum);
}
}
实际执行的结果显示各个线程对静态方法的访问是交叉执行的,但是这并不影响各个线程静态方法print()中sum值的计算。也就是说,在此过程中没有使用全局变量的静态方法在多线程中是安全的,静态方法是否引起线程安全问题主要看该静态方法是否对全局变量(静态变量static member)进行修改操作。
在多线程中使用同一个静态方法时,每个线程使用各自的实例字段(instance field)的副本,而共享一个静态字段(static field)。所以说,如果该静态方法不去操作一个静态成员,只在方法内部使用实例字段(instance field),不会引起安全性问题。
但是,如果该静态方法操作了一个静态变量,则需要静态方法中采用互斥访问的方式进行安全处理。我们来看一下没有使用互斥访问的话会产生怎样的问题:public class StaticAction {
public static int i = 0;
public static void incValue() {
int temp = StaticAction.i;
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
temp++;
StaticAction.i = temp;
}
}
public class StaticThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
StaticAction.incValue();
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new StaticThread()).start();
}
try {
Thread.sleep(1000); //预留足够的时间让上面的线程跑完
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(StaticAction.i);
}
}
实际运行结果显示i值为随机的数字。为了实现互斥访问,这时我们需要加入一个synchronized关键字。代码修改如下:
public class StaticAction {
public static int i = 0;
public synchronized static void incValue() {
int temp = StaticAction.i;
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
temp++;
StaticAction.i = temp;
}
}
public class StaticThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
StaticAction.incValue();
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new StaticThread()).start();
}
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(StaticAction.i);
}
}
运行结果则必然是100。
加入synchronized关键字的静态方法称为同步静态方法。
在访问同步静态方法时,会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。这个其实就是操作系统中的用信号量实现进程的互斥与同步问题,如果涉及在同一个类中有多个静态方法中处理多线程共享数据的话,那就变成用信号量解决生产者-消费者问题。也就是说,静态方法是一份临界资源,对静态方法的访问属于进入临界区;对静态变量的修改是一份临界资源,对静态变量的修改属于进入临界区。
全部回答
也许会有问题,要看你的方法里面写了什么逻辑咯
一般静态方法里如果没有共享资源(全局变量或缓存等)或者锁(不会产生资源竞争)的话,是没问题的
多线程通常主要怕资源争抢问题发生,如果你调用的类只是一个访问不修改值,不存在问题。
如果修改就会带来资源混乱,这时就得作出相应的处理,加锁同步。
并发能产生问题的情况是,两个线程都去竞争同一个对象才会产生问题,如果你的静态方法只是简单的逻辑是不会有问题的,但是如果你的线程都是去修改静态变量的值的话,应该是会造成线程问题的
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
加热沸点在60一80℃间的苯、乙醇、氯仿等可用
单选题下列说法中关于感性认识、理性认识、实
北华大学的美术系实力怎样啊???急求
在操场上努力奔跑的成语
在黄岛买房哪里好
友缘牛杂特色美食府地址有知道的么?有点事想
淄川区东坪镇山头村为什么改名为大喜庄
1.《独坐敬亭山》是_代诗人_写的。诗句“_,_
哪一类生态系统不完全属于自然生态系统AA. 农
描写农村环境的词语
孕妇怎样知道宫口开了
荆州开发区新华卫生室地址在哪,我要去那里办
甘城光辉游乐园有第二季吗?又或者没有都要详
中国福建省福州市鼓楼区有哪些邮编
梁盈有多少个人叫这个名字!
推荐资讯
宁夏红枸杞产业集团的头茬枸杞怎么食用呢?
【舒婷祖国】舒婷的《祖国啊我亲爱的祖国》的
keep an empty city,and an old man 中文什
棉混纺 纯棉的区别
永久阻燃棉、阻燃棉、防火棉和普通棉的区别是
except用to do还是doing?看了很多网上的东西
ipa自动安装什么意思
中国婚纱品牌有哪些 中国婚纱品牌排行榜
氧化铁皮品味
问道绿装备还能在上面加属性吗
【导光光纤】要使光纤导光必须使()
大家能说说你们第一次工作时的状态吗,紧张吗
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?