------- android培训、java培训、期待与您交流! ----------
线程安全问题产生的原因:
1,多个线程在操作共享的数据。
2,操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。
就会导致线程安全问题的产生。
解决思路; 就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程时不可以参与运算的。 必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。在java中,用同步代码块就可以解决这个问题。
同步代码块的格式:
synchronized(obj)
{需要被同步的代码
}
对象如同锁,持有锁的线程可以在同步中执行,否则,即使获取cpu的执行权,也不能进去
同步的前提:
1. 必须有>=2个以上的线程
2. 必须是多个线程使用同一个锁
好处: 解决了多线程的安全问题
弊端: 多个线程需要判断,较为消耗资源。
同步函数使用的锁是 this:同步函数需要被对象调用,函数都有一个所属对象引用,就是this
验证如下:2个线程买票,一个线程在同步代码块,一个在同步函数。
<span style="font-size:12px;">class Ticket implements Runnable {
private int tick = 300;
Object obj = new Object();
boolean flag = true;
public void run() {
if (flag) {
while (true) {
synchronized (this) {
if (tick > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()
+ "...codeblock..." + tick--);
}
}
}
} else
while (true)
show();
}
public synchronized void show() {
if (tick > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()
+ "...codeblock..." + tick--);
}
}
}
public class TicketLockDemo {
public static void main(String[] args)
{
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);} catch(Exception e){}
t.flag = false;
t2.start();
}
}</span>
单例设计模式之懒汉式:
<span style="font-size:12px;">class Single
{
public static final Single s = new Single();
private Single(){};
public static Single getInstance()
{
return s;
}
}</span>
单例设计模式之饿汉式(多线程):
区别:延迟加载
造成问题:如果多线程访问时或有安全问题
解决办法:可以加同步来解决(同步的锁是该类所属的字节码对象),同步代码块或同步函数都能解决,但有些低效,用双重判断的方法可以解决(减少判断的次数)
<span style="font-size:12px;">class Single
{
public static Single s = null;
private Single(){};
public static Single getInstance()
{
if(s==null)
{
synchronized (Single.class) //静态方法的锁是.class
{
if(s==null)</span>
<span style="font-size:12px;"><span style="white-space:pre"> </span>//---->A
s = new Single();
}
}
return s;
}
} //分析:A线程通过第一个if语句,获得锁,通过第二个if语句,挂载;这时B线程通过第一个if语句,获取不到锁,不能继续执行;A线程继续执行,s!=null,这时其他线程不可能通过第一个if语句,不会向下执行。</span>
死锁:同步中嵌套同步。<span style="font-size:12px;">class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
synchronized (MyLock.locka)
{
System.out.println("if locka");
synchronized (MyLock.lockb)
{
System.out.println("if lockb");
}
}
}
else
{
synchronized (MyLock.lockb)
{
System.out.println("else lockb");
synchronized (MyLock.locka)
{
System.out.println("else locka");
}
}
}
}
}
class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
}
public class DeadLockTest {
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
}
}</span>