java多线程(二)---线程的同步

时间:2022-12-22 23:25:22

我们知道多线程存在一些安全性问题,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);
}
}