Android 线程及GLThread同步

今天主要介绍一下glthread和普通thread,以及线程同步问题

1、thread


    首先来说什么是一个线程,说到线程,提一下进程,什么算一个进程呢,一般来说一个app算一个进程,比如说qq,微信,包括手机里的短信,打电话,都是一个进程;
    了解进程,那么,线程就是一个进程的一个单元;一个进程有多个线程,比如qq发送消息、下载图片、视频等都是一个线程
    首先来说普通thread,一般用来解决网络请求等一些耗时操作,使ui线程也就是主线程保证畅通;一般在我们使用手机的时候会有时候出现当前无响应,是等待还是关闭应用;这个就是由于ui线程,执行一个事件没有执行过来,一般界面性的大概就是5秒左右,通知10秒,服务20秒;或者说looper轮询器被什么阻塞

2、glthread


    glthread是glsurfaceview自带的一个渲染线程,同步的,不阻塞主线程;主要用来执行opengl绘制工作;
    下面说一下它的同步原理:
        说同步原理之前先说一下glsurfaceview渲染方式,主动和被动两种
        1、glthread继承与thread,里面有类型为runnable接口一个集合;
        在线程方法中执行一个无限循环while(true){};里面有一个mRequestRender一个boolean值;
        当主动渲染方式,不用说它一直为true,
        当被动渲染方式,那么它需要通过glthread.requestRender();方法去修改mRequestRender的值;
        当这个值为true时,在无线循环中会取runnable集合的第一个event执行;

那么是如何保证线程同步的呢

3、线程同步

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题。

synchronized
    保证当前只有一个线程执行synchronized修饰的代码

    使用方法有同步方法(synchronized修饰方法) 同步代码块(synchronized包含的代码块)
    如果多个线程执行类的一个方法,那么同步方法和同步代码块的作用是一样的

    保证多个线程执行类的多个方法,只有一个线程执行,那么需要保证多个方法的同步锁唯一,这里说一下静态方法,静态方法可以通过类名直接调用,所以它的锁就相当于类名.class;如果非要用类的实例对象调用,那么它的锁就是this;

ReentrantLock
    作用和同步锁一样,保证线程同步
    创建一个ReentrantLock实例 
    lock() : 获得锁 
    unlock() : 释放锁


Volatile和atomic一起说
    Volatile 字面意思是易变的,它也是一个java的关键字,它具有synchronized的可见特性,不具备原子性;
    那什么是可见特性,什么是原子性呢

    可见性,说这个可见性,那么就要说一下jvm运行时的内存分配机制;每一个线程都有一个线程栈,线程栈保存了线程运行的变量信息,当一个线程访问某一个对象的值,首先通过对象的引用找到对应堆内存变量的值,然后将这个值load到这个线程的内存,建立一个变量副本,之后就不再和堆内存的变量值有关系,而是直接修改副本的变量值,在修改完成后,在某一时刻将副本变量值写到堆内存对象变量值,这样堆内存的变量值就变化了。

    那么再回来说可见性,volatile修饰的变量,只能保证从主内存加载到线程内存时,保证变量值是最新的。


    原子性:何谓原子性操作,即为最小的操作单元,比如i=1,就是一个原子性操作,这个过程只涉及一个赋值操作。又如i++就不是一个原子操作,它相当于语句i=i+1;这里包括读取i,i+1,结果写入内存,三个操作单元。因此如果操作不符合原子性操作,那么整个语句的执行就会出现混乱,导致出现错误的结果,从而导致线程安全问题。

    所以volatile并不能完全保证线程安全问题

    那么说一下atomic它主要包括四类:基本类型,数组类型,属性原子修改器类型,引用类型。

    基本类型的类主要包括AtomicInteger、AtomicLong、AtomicBoolean等;
    数组类型主要包括AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray;
    属性原子修改器类型主要包括AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater;
    引用类型主要包括AtomicReference、AtomicStampedRerence、AtomicMarkableReference。

    当以上类创建的对象,可以保证原子性;


 

测试demo

package com.fengmap.threaddemo;


public class ThreadTest {

    static class Bank {

        synchronized void show(String msg) {
            for (int i = 0; i < 100; i++) {
                System.out.println(msg + i);
            }
        }

        static void show33(String msg) {
            synchronized (Bank.class) {
                for (int i = 0; i < 100; i++) {
                    System.out.println(msg + "--show33--" + i);
                }
            }
        }

        synchronized void show22(String msg) {
            for (int i = 0; i < 100; i++) {
                System.out.println(msg + "--show22--" + i);
            }
        }
    }

    public static void main(String[] args) {
        final Bank bank = new Bank();
        new Thread() {
            @Override
            public void run() {
                bank.show("第一个线程");
                bank.show22("第一个线程");
                Bank.show33("第一个静态线程");
            }
        }.start();

        new Thread() {
            @Override
            public void run() {
                bank.show("第二个线程");
                bank.show22("第二个线程");
                Bank.show33("第二个静态线程");
            }
        }.start();

        bank.show("主线程");
        Bank.show33("静态主线程");
    }
}

 

你可能感兴趣的:(java)