我们知道多线程存在一些安全性问题,java为多线程提供给了一个解决多线程安全问题的关键字synchronized。
同步的前提
1、具有两个及以上的线程
2、必须是多个线程使用同一个锁
java提供了Synchronized来解决多线程的安全性问题。
好处:可以解决多线程的安全问题
弊端:每次都要判断锁,耗费系统资源。
同步代码块
synchronized(对象){
//需要加锁的代码块..
}
这个例子演示同步的作用及意义。
public class DemoSync{
public static void main(String args[]){
DemoRunnable dr = new DemoRunnable();
Thread t1 = new Thread(dr);
Thread t2 = new Thread(dr);
Thread t3 = new Thread(dr);
Thread t4 = new Thread(dr);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class DemoRunnable implements Runnable{
private int ticket=100;
Object obj = new Object(); //相当于传入的对象锁
public void run(){
while(true){
synchronized(obj){
if(ticket>0){
try{
Thread.sleep(10);
}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--售票:"+ticket--);
}else{
System.exit(1);
}
}
}
}
}
同步函数的使用
非静态方法的同步,即用synchronized修饰非静态的方法。
private synchronized void add(int m)
多线程代码块的对象锁是 this,即当前对象的引用。
静态方法的同步,用synchronized修饰静态的方法
因为静态方法进入内存以后并没有产生对象,因此不可能是this,
通过验证,多线程代码块的对象锁是类.class.
问题描述
有两个储户分别到银行存300元,每次存入100元,分3次存储。分析是否存在安全性问题。
如何找问题:
1、明确哪些代码是多线程运行代码
2、明确共享数据
3、明确多线程运行代码中哪些语句是操作共享数据的。
public class ThisLockDemo{
public static void main(String args[]){
MyRunnable dr = new MyRunnable();
StaMyRunnable smr = new StaMyRunnable();
Thread t1 = new Thread(dr);
Thread t2 = new Thread(smr);
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable{
private int sum = 0;
public void run(){
for(int i=0;i<3;i++){
add(100);
}
}
private synchronized void add(int m){
sum += m;
System.out.println(Thread.currentThread().getName()+"存储:"+sum);
}
}
class StaMyRunnable implements Runnable{
private static int sum = 0;
public void run(){
for(int i=0;i<3;i++){
add(100);
}
}
private static synchronized void add(int m){
sum += m;
System.out.println(Thread.currentThread().getName()+"存储:"+sum);
}
}