C++ multi-threading demo
Prefer using a lock guard: 

int city_index = 0;
{
    std::lock_guard&lt;std::mutex&gt; guard(city_counter_lock);
    if (current_city + 1 &lt; (int) cities.size()) {
        city_index = ++current_city;
    }
}


This makes sure that an exception will not leave the mutex locked;



You will need to handle failures to get the webpage. If res != CURLE_OK then a failure occurred somewhere.



You are encouraged to reuse the CURL handle you can do so by creating it inside fetch_weather_async before the loop and passing it into fetchJson

void fetch_weather_async(){
    CURL *curl;

    curl = curl_easy_init();

    if(!curl) return;
    while (current_city + 1 &lt; (int) cities.size()){
        int city_index = 0;
        {
            std::lock_guard&lt;std::mutex&gt; guard(city_counter_lock);
            if (current_city + 1 &lt; (int) cities.size()) {
                city_index = ++current_city;
            }
        }

        std::cout &lt;&lt; "requesting " &lt;&lt; city_index &lt;&lt; std::endl;  
        fetchJson(city_index, curl);
        std::cout &lt;&lt; "acquired " &lt;&lt; city_index &lt;&lt; std::endl;    
    }
    curl_easy_cleanup(curl);
}

void fetchJson(int i, CURL *curl){    
    CURLcode res;
    std::string readBuffer;


    curl_easy_setopt(curl, CURLOPT_URL, (URL_BASE + cities[i]).c_str());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &amp;readBuffer);
    res = curl_easy_perform(curl);
    if(res == CURLE_OK)
        std::cout &lt;&lt; i &lt;&lt; " : " &lt;&lt; readBuffer &lt;&lt; std::endl;

}