一个连胡说八道都说不好的程序员.

  • Java并发实现之关键字Volatile


    作用

    在Java中,关键字 volatile 用来修饰类的成员变量,意味着任何对该变量的访问都需要从共享内存中读取,而非从本地私有内存(Local Memory)中读取。且对变量值的改变也必须同步写回到共享内存。在Java并发中,volatile 关键字能保证所有线程对访问变量的可见性。

    解释

    在Java中,线程之间的通信是通过共享内存来实现的(线程之间共享堆内存,通过读写来进行通信)。所有的线程都有自己的本地私有内存(Local Memory),本地私有内存存放有该线程需要读写的共享变量的副本。因为这个副本的存在,不同线程之间读取同一个共享变量的值有可能是已经过期了的。 在读写一个Volatile修饰的变量时候,按照下面的方法进行处理:

    1. 当更新Volatile变量时候,会把对应本地内存中共享变量值写回住内存中。
    2. 当读取Volatile变量时候,将会标记本地内存中值无效,然后从主内存中读取对应的共享变量的值。

    正确使用

    Volatile 变量具有可见性,但是不具备原子特性,要使 volatile 变量提供理想的线程安全,需要同时满足下面两个条件: 来自《正确使用 Volatile 变量》

    1. 对变量的写操作不依赖于当前值。
    2. 该变量没有包含在具有其他变量的不变式中。

    所以只是实用Volatile来修饰变量想要实现计数器,这是不安全的。因为我们对一个变量进行x+=1或者x++操作的时候,实际上这是一个读取值,修改值,最后写入三个序列操作组成的组合操作,必须以原子方式执行,而 volatile 不能提供必须的原子特性。

    对指令重排的影响

    volatile语义保证了volatile变量在一些情况下不会重排序,volatile的64位变量double和long的读取和赋值操作都是原子的。下表为 volatile重排序规则。

    能否重排序 第二操作
    第一操作 普通读写 volatile读 volatile写
    普通读写 NO
    volatile读 NO NO NO
    volatile写 NO

  • 让Xcode在Archive的时候自动增加Target的Build号


    注: 关于xcode中target的Build作用还有其和Version的关系和区别,如果不明白的,可以看下官方的文档:Version Numbers and Build Numbers

    那么, 如果要让Build Numbers能自动增长呢?

    首先,在项目目录下新建个bash文件,我这里取名为 buildseqence.sh, 代码如下

    #!/bin/sh
    
    #  buildseqence.sh
    #  Aircraft
    #
    #  Created by cluries on 12/8/10.
    #  Copyright © 2012年 cluries. All rights reserved.
    
    if [ $# -ne 1 ]; then
        echo usage: $0 plist-file
        exit 1
    fi
    
    plist="$1"
    dir="$(dirname "$plist")"
    
    if [ "Debug" = ${CONFIGURATION} ]; then
        echo "Not incrementing build number as Debug model."
        exit 0
    fi
    
    
    buildnum=$(/usr/libexec/Plistbuddy -c "Print CFBundleVersion" "$plist")
    if [ -z "$buildnum" ]; then
        echo "No build number in $plist"
        exit 2
    fi
    
    buildnum=$(expr $buildnum + 1)
    /usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "$plist"
    echo "Incremented build number to $buildnum"
    
    

    然后进入在Target中的Build Phases添加Run Script:

    ${PROJECT_DIR}/Aircraft/buildseqence.sh "${PROJECT_DIR}/${INFOPLIST_FILE}"
    

    这样,在每次Xcode Archive操作的时候,都可以自动增加Build Number, 如果想要在Debug的时候也能自动增加,去掉Bash脚本中的下面代码就可以了:

    if [ "Debug" = ${CONFIGURATION} ]; then
        echo "Not incrementing build number as Debug model."
        exit 0
    fi
    

  • 解决通过Cocoapods安装或升级Realm时候CURL报SSLRead()的错误


    今天Realm提醒我有新版本可用。但是在pod update中报错了,如下:

     > Running prepare command
       $ /usr/local/bin/bash -c  set -e sh build.sh cocoapods-setup
       core is not a symlink. Deleting...
       Downloading dependency: core 0.100.0
       Downloading core failed:
       curl: (56) SSLRead() return error -9806
    [!] /usr/local/bin/bash -c 
    set -e
    sh build.sh cocoapods-setup
    
    core is not a symlink. Deleting...
    Downloading dependency: core 0.100.0
    Downloading core failed:
    curl: (56) SSLRead() return error -9806
    

  • RVM安装ruby 1.9.3时候错误


    因为动态库位置的变动,之前编译的ruby 1.9.3版本运行不起了,然后不想 ln -s 一下,需要重新编译ruby 1.9.3。

    rvm reinstall 1.9.3 后在编译过程中报错 :

    regparse.c:582:15: error: implicit conversion loses integer precision: 'st_index_t' (aka 'unsigned long') to 'int' [-Werror,-Wshorten-64-to-32]
        return t->num_entries;
    

    ** -Werror,-Wshorten-64-to-32 ** 编译参数和错误提示倒是很明确,不过因为是通过rvm安装的,又不能直接去修改Makefile。

    Github上解决方法是 CC=gcc rvm install 1.9.3

    这样也可以,不过适合于xcode5之前的版本,如果安装的是xcode5,因为xcode5里并没有包含llvm-gcc,所以这样是不行的。

    在安装了xcode5情况下,gcc还是clang,所以需要手动安装gcc4.2.

    通过homebrew可以快速安装: brew install apple-gcc42

    然后CC=/usr/local/Cellar/apple-gcc42/4.2.1-5666.3/bin/gcc-4.2 rvm install 1.9.3 后就等着rvm帮忙安装1.9.3了。


  • ffmpeg编译iOS静态库教程


    本文大部分内容参考于此篇文章:How to Prepare Your Mac for iOS Development with FFmpeg Libraries , 然后针对最新情况做了一些修改。

    1. 首先,准备编译环境

    1. 安装Xcode和Command Line Tools
    2. 下载和安装 gas-preprocessor
    3. 安装 pkg-config
    

    关于gas-preprocessor,安装方式是直接copy文件 gas-preprocessor.pl/usr/bin ,记得修改权限可执行.